Using InputStream as :ssl-context :trust-store is buggy #728
Description
Quoting the original report by @David-Ongaro from the addendum of #727:
As per the docs, instead of
java.io.File
instances,java.io.InputStream
instances are also supported as keys for the:ssl-context
map. But I can't figure out how this is supposed to be used, as I regularly getjava.lang.IllegalArgumentException: Input stream does not contain valid certificates.
exceptions. I.e., preparing a single request just works fine, but preparing them in quick succession may fail:(def ssl-context {:trust-store (io/input-stream client-ca)}) (def pool (http/connection-pool {:connection-options {:ssl-context ssl-context}})) (http/get "https://example.com" {:pool pool}) => #<Deferred@6fb6283a: :not-delivered> [(http/get "https://example.com" {:pool pool}) (http/get "https://example.com" {:pool pool})] => [#<Deferred@58ac8429: Error printing return value (CertificateException) at io.netty.handler.ssl.PemReader/readCertificates (PemReader.java:114). Error printing return value (CertificateException) at io.netty.handler.ssl.PemReader/readCertificates (PemReader.java:114). found no certificates in input stream PemReader.java: 114 io.netty.handler.ssl.PemReader/readCertificates SslContext.java: 1263 io.netty.handler.ssl.SslContext/toX509Certificates SslContextBuilder.java: 276 io.netty.handler.ssl.SslContextBuilder/trustManager netty.clj: 917 aleph.netty/eval23500/add-ssl-trust-manager! netty.clj: 1026 aleph.netty/eval23500/ssl-client-context netty.clj: 1193 aleph.netty/coerce-ssl-context netty.clj: 1179 aleph.netty/coerce-ssl-context core.clj: 2641 clojure.core/partial/fn client.clj: 699 aleph.http.client/client-ssl-context client.clj: 690 aleph.http.client/client-ssl-context client.clj: 799 aleph.http.client/http-connection client.clj: 752 aleph.http.client/http-connection http.clj: 104 aleph.http/create-connection http.clj: 97 aleph.http/create-connection http.clj: 239 aleph.http/connection-pool/fn flow.clj: 47 aleph.flow/instrumented-pool/reify Pool.java: 273 io.aleph.dirigiste.Pool/addObject Pool.java: 466 io.aleph.dirigiste.Pool/acquire flow.clj: 74 aleph.flow/acquire/fn flow.clj: 73 aleph.flow/acquire flow.clj: 68 aleph.flow/acquire http.clj: 377 aleph.http/eval30155/request/fn/fn http.clj: 371 aleph.http/eval30155/request/fn http.clj: 370 aleph.http/eval30155/request http.clj: 481 aleph.http/req http.clj: 477 aleph.http/req core.clj: 2642 clojure.core/partial/fnI didn't look into the implementation, but I suspect what's happening here is that when the first thread of the thread pool is initialized, it's exhausting the input-stream instance and this instance is reused during the initialization of a second thread. (At least that's what I hope is happening, since the alternative would be that each thread tries to reread the certificate on each request.)
So the question is, if this doesn't work, why is it even supported? But if this is indeed an issue, it probably should be handled in a separate ticket, since this behavior already applies to Aleph 0.6.4 and therefore can't be considered a regression.