spring-cloud / spring-cloud-release

Spring Cloud Release Train - dependency management across a wide range of Spring Cloud projects.
http://projects.spring.io/spring-cloud
Apache License 2.0
877 stars 180 forks source link

SSLPeerUnverifiedException when migrating from Brixton.M3 to Brixton.RELEASE #53

Closed fiallega closed 8 years ago

fiallega commented 8 years ago

Using spring-boot 1.3.5 and org.springframework.cloud when using zuul proxy

with version: Brixton.M3 everything works fine.

When we upgraded to Brixton.RELEASE we get the following exception javax.net.ssl.SSLPeerUnverifiedException: Host name 'localhost' does not match the certificate subject provided by the peer (CN=test, OU=test County, O=test, L=Miami, ST=Florida, C=us)

What do you suggest we do in order to migrate the version.

Thanks

spencergibb commented 8 years ago

Can you provide some steps to reproduce the issue? Maybe a sample project?

pcornelissen commented 8 years ago

I'm encountering the same problem.

I can't share the service though...

I get: 14:36:14.652 [main] DEBUG org.apache.http.wire - http-outgoing-5 << "{"timestamp":1464957374647,"status":500,"error":"Internal Server Error","exception":"javax.net.ssl.SSLPeerUnverifiedException","message":"Host name 'localhost' does not match the certificate subject provided by the peer (CN=Tom Akehurst, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown)"}" The setup is pretty simple, I have a zuul service that just relays the request to a wiremock instance via https.

This is the important part of the test:

    @Rule
    public TestCasePrinterRule pr = new TestCasePrinterRule(System.out);
    @Rule
    public WireMockRule wireMockRule = new WireMockRule(wireMockConfig()
            .port(7777)
            .httpsPort(Integer.valueOf(System.getProperty("targetPort", "48443"))));
    private String serverUrl;

    @Before
    public void before() throws IOException {
        System.out.println("Wiremock Port: " + System.getProperty("targetPort", "48443"));
        serverUrl = "https://" + hostname + ":8443/";
    }

    @Test
    public void jsonContentIsNotTouched() throws IOException {
        String content = getFile("json-content.json");
        String uri = "/userservice-userservice-impl/my/json/test";
        stubFor(post(urlEqualTo(uri))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withHeader("Content-Type", "application/json")
                        .withBody("{message:'Okily dokily!'}")));

        RestResponse<byte[]> response = simpleRestClient.post(serverUrl + uri)
                .entity(new StringEntity(content, org.apache.http.entity.ContentType.create((MediaType.APPLICATION_JSON))))
                .execute();
        assertThat(response.getStatus(), Matchers.is(200));

        verify(postRequestedFor(urlMatching(uri))
                .withRequestBody(equalTo(content))
                .withHeader("Content-Type", matching("application/json")));
    }

Does this help? Until this is resolved I revert to Angel.SR6.

dsyer commented 8 years ago

Tom Akehurst is the author of Wiremock. It looks like the certificate is his. Maybe you need to ask him how to configure the server or client to avoid trust issues?

pcornelissen commented 8 years ago

Hmm, well, this is a self signed certificate which is not unusual at least in development environments and after Brixton.M3 we are getting these errors from the zuul based spring cloud service. When you do the calls yourself you can usually just configure a HostnameVerifier for the ConnectionFactory which ignores the hostname, but I wasn't successful yet to find a way to configure this for the http client zuul/ribbon uses. Maybe it's a zuul problem because the zuul version changed from .M3 to .RELEASE. I haven't investigated this more, but how should we know where to fix this? I would hope that the spring-cloud team or the netflix guys can shed some light on this issue :-)

dsyer commented 8 years ago

It looks like you have some experience solving this kind of problem, so maybe you can dig a bit more to find out how to configure the HTTP client?

pcornelissen commented 8 years ago

Hmmm, I may be able to spend a few hours, but honestly I currently have more work than time already ;-)

ali2992 commented 8 years ago

Was this ever resolved? The HTTPClient object in RibbonLoadBalancingHttpClient is a private final field that is initialised inside the class, theres no access to even call the setDefaultHostnameVerifier override that would allow to bypass the verification check - the only way I can see to do it would be to create your own RibbonLoadBalancingClient that allows you to set the client, but that seems like a horrible hack and will add a lot of redundant code

dsyer commented 8 years ago

The issue is still open, and still marked as "help wanted". I know that @ryanjbaxter is looking at updating the way the client gets created, so maybe he could take a look when he gets to it.

spencergibb commented 8 years ago

@ali2992 https://github.com/spring-cloud/spring-cloud-netflix/commit/9eed2490288a2d218d80e7498de861d851ef9c19 just introduced a constructor that allows you to pass an HttpClient object.

ryanjbaxter commented 8 years ago

I think @spencergibb's solution should work based on the code he introduced. Can we close this issue then? If not I think we should move it to Spring Cloud Netflix instead of here.

spencergibb commented 8 years ago

Please open a new issue here if you think this is still a problem.

jzampieron commented 8 years ago

Is there a quick solution to this issue when using "the whole stack", meaning Eureka, Ribbon and Zuul within Spring Boot?

I believe that adding: ribbon: CustomSSLSocketFactoryClassName: com.netflix.http4.ssl.AcceptAllSocketFactory IsHostnameValidationRequired: false

To the application.yml file does it, but I'm wondering if people have any better ideas.