Ошибка при маршрутизации Zuul на HTTPS URL
У меня есть приложение Spring Boot (недавно оно было включено для HTTPS + самозаверяющий сертификат), зарегистрированное в Eureka и видимое на информационной панели Eureka.
У нас есть слой Zuul Filter, который получает запрос пользователя и затем передает его приложению Spring Boot. Это работало нормально, пока приложение не было доступно через HTTP. Но, как только я включил HTTPS, маршрутизация zuul терпит неудачу.
Вот конфигурация маршрута Zuul в моем файле yaml. Должна ли моя конфигурация Zuul Route иметь какую-либо специальную конфигурацию для URL/ приложения с поддержкой HTTPS?
zuul:
routes:
ms:
path: /app/**
stripPrefix: true
ms:
ribbon:
ServerListRefreshInterval: 1000
ConnectTimeout: 20000
ReadTimeout: 20000
Вот трассировка стека исключений (показывающая, что Zuul пытается перенаправить URL-адрес HTTP вместо URL-адреса HTTPS)
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: msRibbonCommand failed and no fallback available.
at com.netflix.hystrix.AbstractCommand$20.call(AbstractCommand.java:816) ~[hystrix-core-1.4.0-RC6.jar:na]
at com.netflix.hystrix.AbstractCommand$20.call(AbstractCommand.java:798) ~[hystrix-core-1.4.0-RC6.jar:na]
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:76) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$ThrowObservable$1.call(Observable.java:10493) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$ThrowObservable$1.call(Observable.java:10483) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:77) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:48) ~[rxjava-core-0.20.7.jar:na]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:318) ~[hystrix-core-1.4.0-RC6.jar:na]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:310) ~[hystrix-core-1.4.0-RC6.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:77) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:48) ~[rxjava-core-0.20.7.jar:na]
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$3.onError(AbstractCommand.java:995) ~[hystrix-core-1.4.0-RC6.jar:na]
at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$ThrowObservable$1.call(Observable.java:10493) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$ThrowObservable$1.call(Observable.java:10483) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:77) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:48) ~[rxjava-core-0.20.7.jar:na]
at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:301) ~[hystrix-core-1.4.0-RC6.jar:na]
at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:293) ~[hystrix-core-1.4.0-RC6.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
at com.netflix.hystrix.AbstractCommand$1.call(AbstractCommand.java:388) ~[hystrix-core-1.4.0-RC6.jar:na]
at com.netflix.hystrix.AbstractCommand$1.call(AbstractCommand.java:368) ~[hystrix-core-1.4.0-RC6.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
at com.netflix.hystrix.AbstractCommand$ObservableCommand$1.call(AbstractCommand.java:1097) ~[hystrix-core-1.4.0-RC6.jar:na]
at com.netflix.hystrix.AbstractCommand$ObservableCommand$1.call(AbstractCommand.java:1093) ~[hystrix-core-1.4.0-RC6.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable.subscribe(Observable.java:8680) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.BlockingOperatorToFuture.toFuture(BlockingOperatorToFuture.java:55) ~[rxjava-core-0.20.7.jar:na]
at rx.observables.BlockingObservable.toFuture(BlockingObservable.java:420) ~[rxjava-core-0.20.7.jar:na]
at com.netflix.hystrix.HystrixCommand.queue(HystrixCommand.java:385) ~[hystrix-core-1.4.0-RC6.jar:na]
at com.netflix.hystrix.HystrixCommand.execute(HystrixCommand.java:339) ~[hystrix-core-1.4.0-RC6.jar:na]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:130) ~[spring-cloud-netflix-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
... 82 common frames omitted
Caused by: com.netflix.client.ClientException: null
at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:123) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:81) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand.forward(RibbonCommand.java:129) ~[spring-cloud-netflix-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand.run(RibbonCommand.java:103) ~[spring-cloud-netflix-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand.run(RibbonCommand.java:1) ~[spring-cloud-netflix-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:298) ~[hystrix-core-1.4.0-RC6.jar:na]
... 125 common frames omitted
Caused by: org.apache.http.client.ClientProtocolException: null
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:867) ~[httpclient-4.3.6.jar:4.3.6]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:115) ~[httpclient-4.3.6.jar:4.3.6]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57) ~[httpclient-4.3.6.jar:4.3.6]
at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:170) ~[jersey-apache-client4-1.11.jar:1.11]
at com.sun.jersey.api.client.Client.handle(Client.java:648) ~[jersey-client-1.13.jar:1.13]
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:680) ~[jersey-client-1.13.jar:1.13]
at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) ~[jersey-client-1.13.jar:1.13]
at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:568) ~[jersey-client-1.13.jar:1.13]
at com.netflix.niws.client.http.RestClient.execute(RestClient.java:621) ~[ribbon-httpclient-2.0-RC13.jar:na]
at com.netflix.niws.client.http.RestClient.execute(RestClient.java:527) ~[ribbon-httpclient-2.0-RC13.jar:na]
at com.netflix.niws.client.http.RestClient.execute(RestClient.java:92) ~[ribbon-httpclient-2.0-RC13.jar:na]
at com.netflix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:109) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:54) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:41) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:30) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorConcat$ConcatSubscriber.subscribeNext(OperatorConcat.java:163) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorConcat$ConcatSubscriber.onNext(OperatorConcat.java:128) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorConcat$ConcatSubscriber.onNext(OperatorConcat.java:65) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:54) ~[rxjava-core-0.20.7.jar:na]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:112) ~[rxjava-core-0.20.7.jar:na]
at rx.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:85) ~[rxjava-core-0.20.7.jar:na]
at rx.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:65) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:77) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:41) ~[rxjava-core-0.20.7.jar:na]
at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:30) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
at rx.Observable.subscribe(Observable.java:8680) ~[rxjava-core-0.20.7.jar:na]
at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:452) ~[rxjava-core-0.20.7.jar:na]
at rx.observables.BlockingObservable.single(BlockingObservable.java:348) ~[rxjava-core-0.20.7.jar:na]
at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:102) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
... 130 common frames omitted
Caused by: org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:151) ~[httpclient-4.3.6.jar:4.3.6]
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57) ~[httpclient-4.3.6.jar:4.3.6]
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:261) ~[httpcore-4.4.jar:4.4]
at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:283) ~[httpcore-4.4.jar:4.4]
at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:251) ~[httpclient-4.3.6.jar:4.3.6]
at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:223) ~[httpclient-4.3.6.jar:4.3.6]
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:272) ~[httpcore-4.4.jar:4.4]
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124) ~[httpcore-4.4.jar:4.4]
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:685) ~[httpclient-4.3.6.jar:4.3.6]
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:487) ~[httpclient-4.3.6.jar:4.3.6]
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863) ~[httpclient-4.3.6.jar:4.3.6]
Обновление: после добавления свойства безопасности isRibbon эта ошибка исчезла, и теперь у меня новая ошибка.
1 ответ
Прошло немного времени с тех пор, как я поиграл с этим, потому что в итоге мы не смогли его использовать из-за ограничения неспособности передать сертификат пользователя через прокси. Тем не менее, вы попросили мою помощь, поэтому я постараюсь поделиться тем, что у меня было работать.
Мне удалось получить двухсторонний SSL, работающий как между ZUUL, действующим в качестве пограничного сервера, так и с сервисами на бэкэнде, когда они работали на своих собственных виртуальных машинах (т.е. выполняли mvn spring-boot: run для каждой службы).
Вот мой Zuul Conifg:
info:
component: Zuul Server
endpoints:
restart:
enabled: true
shutdown:
enabled: true
health:
sensitive: false
zuul:
routes:
ui: /**
api: /api/**
logging:
level:
ROOT: INFO
org.springframework.web: DEBUG
server:
port: 8443
ssl:
key-store: classpath:dev/localhost.jks
key-store-password: yourpassword
keyStoreType: JKS
keyAlias: localhost
clientAuth: want
trust-store: classpath:dev/localhost.jks
ribbon:
IsSecure: true
Сам Edge Server ничего интересного:
@SpringBootApplication
@Controller
@EnableAutoConfiguration
@EnableZuulProxy
public class ZuulEdgeServer {
public static void main(String[] args) {
new SpringApplicationBuilder(ZuulEdgeServer.class).web(true).run(args);
}
}
Теперь в других моих службах у меня было следующее в их файлах application.yml:
server:
port: 8444
ssl:
key-store: classpath:dev/localhost.jks
key-store-password: yourpassword
keyStoreType: JKS
keyAlias: localhost
clientAuth: want
trust-store: classpath:dev/localhost.jks
eureka:
instance:
nonSecurePortEnabled: false
securePortEnabled: true
securePort: ${server.port}
homePageUrl: https://${eureka.instance.hostname}:${server.port}/
secureVirtualHostName: ${spring.application.name}
Мой Eureka Config не слишком много, но на всякий случай:
server:
port: 8761
eureka:
client:
registerWithEureka: false
fetchRegistry: false
server:
waitTimeInMsWhenSyncEmpty: 0
Мой bootstrap.yml в большинстве приложений выглядит так:
spring:
application:
name: eureka
cloud:
config:
uri: ${vcap.services.${PREFIX:}configserver.credentials.uri:http://user:password@localhost:8888}
В основном я обнаружил, что мне нужно spring.application.name
для разрешения конфликтов при запуске приложений в одном контейнере.
Если я правильно помню, важными частями сверху были:
ribbon.isSecure = true
в конфиге zuuleureka.instance.securePortEnabled = true
иsecurePort
в бэкэнд-сервисах.
Я не могу вспомнить, если secureVirtualHostName
было важно или нет.
Надеюсь, эта информация поможет вам, хотя!