Possible to use custom SSL Context with HttpClient? #72

Closed
abethell opened this Issue Nov 20, 2012 · 6 comments

Comments

Projects
None yet
4 participants

A RESTful service I use requires SSL authentication - I use the SSLSocketFactory as shown in this example - http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java.

However - when using the SystemDefaultHttpClient, or BetamaxRoutePlanner - I always receive:

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

there is also a warning immediately before this:

javax.net.ssl.SSLException: Received fatal alert: certificate_unknown

Is there something I am missing - or is this not supported yet?

Heres my full test-source - it works fine if I remove the @betamax annotation, or get from a http address:

import java.security.KeyStore;
...

public class BetamaxTest {

    private Logger log = LoggerFactory.getLogger(CountryRepositoryTest.class);

    @Resource
    private RepositoryConfigImpl repositoryConfig;

    @Rule
    public Recorder recorder = new Recorder();

    @Before
    public void setup() {
        recorder.setSslSupport(true);
    }

    @Betamax(tape="thing tape")
    @Test
    public void testGetThingy() throws Exception {

        KeyStore keyStore = repositoryConfig.getKeyStore();
        KeyStore trustStore = repositoryConfig.getTrustStore();

        DefaultHttpClient httpClient = new SystemDefaultHttpClient();

        SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore, "changeit", trustStore);
        Scheme sch = new Scheme("https", 443, socketFactory);
     //   BetamaxRoutePlanner.configure(httpClient);
        httpClient.getConnectionManager().getSchemeRegistry().register(sch);
        HttpGet httpGet = new HttpGet("https://myresthost/REST/account_attribute/97487/");
        HttpResponse response1 = httpClient.execute(httpGet);

        try {
            System.out.println(response1.getStatusLine());
            HttpEntity entity1 = response1.getEntity();
            EntityUtils.consume(entity1);
        } finally {
            httpGet.releaseConnection();
        }
    }
}

Thanks

Collaborator

robfletcher commented Nov 26, 2012

Not supported yet but it's a very good idea

Collaborator

robfletcher commented Jan 3, 2013

Would it make sense to be able to set the SSLSocketFactory instance on the Recorder? It could then be used by the proxy to make the real connection to the target. I'm not sure if it's necessary to set it on the client in your test since Betamax is breaking the certificate chain anyway in order to record traffic. I think this should be simple to implement.

@ghost ghost assigned robfletcher Jan 3, 2013

robfletcher pushed a commit that referenced this issue Jan 3, 2013

failing test for #72
I think the functionality is actually working but I need to come up with a way to verify that the custom SSLSocketFactory is actually getting used.

robfletcher pushed a commit that referenced this issue Jan 4, 2013

#72 configuration for `ProxyRecorder.sslSocketFactory` via groovy config
Don't think it makes sense to support this via properties.

robfletcher pushed a commit that referenced this issue Jan 4, 2013

robfletcher pushed a commit that referenced this issue Jan 4, 2013

Collaborator

robfletcher commented Jan 4, 2013

Fixed. This will be in the next release.

@robfletcher robfletcher closed this Jan 4, 2013

Hi Rob - thanks for adding support for this; I was looking at the 1.2 (multimodule) branch to see if I could test this, but I am a little lost...

If I use the BetamaxHttpClient - it saves the yaml tape files, but only on https://www.google.co.uk - on my secure host I get SSLPeerUnverifiedExceptions.

If I use the DefaultHttpClient then my http GET is successful, but no tapes are recorded.

Any ideas?

Thanks

@ContextConfiguration(locations = {"classpath:test-config.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class BetamaxTest {

    private Logger log = LoggerFactory.getLogger(BetamaxTest.class);

    @Resource
    private RepositoryConfigImpl repositoryConfig;

    @Rule
    public Recorder recorder = new ProxyRecorder();

    @Betamax(tape="test tape")
    @Test
    public void testGetCountry() throws Exception {

        SSLSocketFactory socketFactory = new SSLSocketFactory(repositoryConfig.getKeyStore(),
                "asdfoi2j34",
                repositoryConfig.getTrustStore());

        ((ProxyRecorder)recorder).setSslSupport(true);
        ((ProxyRecorder)recorder).setSslSocketFactory(socketFactory);

        //HttpClient httpClient = new BetamaxHttpClient(recorder);
        HttpClient httpClient = new DefaultHttpClient();


        Scheme sch = new Scheme("https", 443, socketFactory);
        httpClient.getConnectionManager().getSchemeRegistry().register(sch);

        HttpGet httpGet = new HttpGet("https://api-test-host/REST/country/gb");
        //HttpGet httpGet = new HttpGet("https://www.google.com/");
        HttpResponse response1 = httpClient.execute(httpGet);

        try {
            System.out.println(response1.getStatusLine());
            HttpEntity entity1 = response1.getEntity();
            FileCopyUtils.copy(entity1.getContent(),System.out);
            EntityUtils.consume(entity1);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpGet.releaseConnection();
        }
    }

}

My maven pom:

        <dependency>
            <groupId>co.freeside</groupId>
            <artifactId>betamax-core</artifactId>
            <version>1.2-SNAPSHOT</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>co.freeside</groupId>
            <artifactId>betamax-httpclient</artifactId>
            <version>1.2-SNAPSHOT</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>co.freeside</groupId>
            <artifactId>betamax-proxy</artifactId>
            <version>1.2-SNAPSHOT</version>
            <scope>test</scope>
        </dependency>

monksy commented Jul 9, 2015

When will the next release be? 1.1.2 is still the "stable" version.

Contributor

rschmitt commented Jul 9, 2015

Under 20 commits in the last year and a half? It might be time for a fork. You're not the only one tired of waiting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment