HTTP library for Ruby with HTTPS, SSL Client Certificate and Keep-Alive support?
Is there something that already works?
I believe the HTTP client library Faraday is focus of more Ruby community action is these days.
It comes with a :net_http_persistent
adapter, which supports SSL client certificates. You can probably do something like this:
ssl_options = {
cert: OpenSSL::X509::Certificate.new(File.read('./certificate/client-2048.pem')),
key: OpenSSL::PKey::RSA.new(File.read('./certificate/client-2048.key'), 'mypassword')
}
conn = Faraday.new(url: 'https://example.com', ssl: ssl_options) do |faraday|
faraday.adapter = Faraday::Adapter::NetHttpPersistent
end
conn.get '/my-resource'
HTTParty
According to the specs:
... the resulting connection when providing PEM certificates when scheme is https
- uses the provided PEM certificate
- will verify the certificate
You can use the pem
classmethod to provide a client certificate in PEM format.
REST Client
It's not as dead as all that -- Larry Gilbert (@L2G
) is still merging in pull requests and keeping the lights on. He's nodded his general approval in the issue tracker. I suspect it's just not at the top of his priority queue at the moment.
The guy who sent in that pull request, @byroot
, has been keeping his code up to date so you shouldn't need to do much at all while you wait.
How to use a client certificate with HTTPS?
Okay, so I looked all over and found bits and pieces of what I needed. I want to provide this for anyone else that is struggling. All of the files were put in a PEM format. I used the client.key
file to create a CSR that was given to the server administrator. In return I got a P7B file that I then needed to be convert into PEM files. The root.cer
and client.cer
file came from the P7b.
uri = URI.parse(my_url_stril)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.cert = OpenSSL::X509::Certificate.new(File.read("client.cer"))
http.ca_file = 'root.cer'
http.key = OpenSSL::PKey::RSA.new(File.read("client.key"))
request = Net::HTTP::Post.new(uri.request_uri)
request.body = body
response = http.request(request)
Let me know if you need more details!
How to mimic browser X509 client certificate verification without access to HTTP layer
Your app stack isn't able to control SSL cause it's terminated on the web server. All the verification stuff is done by the web server and then only SSL_* headers go to the app server (look for Apache's SSLOptions for example). If you can't control web server you probably cant even turn on client certificate requirement. And i can't find any options to turn this requirement on via heroku: https://devcenter.heroku.com/articles/ssl#customdomain-ssl
If you've got SSL_* headers somehow then, regardless of web-server-side verification, you can verify certificate (commonly in the SSL_CLIENT_CERT header) using openssl as an army knife. See this for example in ruby: OpenSSL verify certificate from own CA
Also keep in mind that certificate verification is the process of checking certificate sign and other properties e.g. formal checking. To authenticate user you have to link that verified certificate to user by DN or E field, for example.
SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)
After lots of testing, I found the correct solution. The problem was with the cert file declaration.
I tried sending the post request using the bundled cert files (example.com.pem)
http.ca_file = File.read(File.join(Rails.root, "/crt/example.com.pem"))
So, I changed the above declaration with the each crt and key files
http.cert = OpenSSL::X509::Certificate.new(File.read(File.join(Rails.root, "/crt/example.com.crt")))
http.key = OpenSSL::PKey::RSA.new(File.read(File.join(Rails.root, "/crt/example.com.key")))
req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/xml'}).
It now worked.
Complete code
uri = URI("https://test.compassplus.com:8444/Exec")
xml = "
<TKKPG>
<Request>
<Operation>CreateOrder</Operation>
<Language></Language>
<Order>
<OrderType>Purchase</OrderType>
<Merchant>99999</Merchant>
<Amount>10000</Amount>
<Currency>524</Currency>
<Description>Tour Purchase</Description>
<ApproveURL>/approve.html</ApproveURL>
<CancelURL>/cancel.html</CancelURL>
<DeclineURL></DeclineURL>
<email></email>
<phone></phone>
<AddParams>
<FA-DATA></FA-DATA>
<SenderPostalCode></SenderPostalCode>
<AcctType></AcctType>
<TranAddendums></TranAddendums>
<TranAddendumsVISA></TranAddendumsVISA>
<TranAddendumsMC></TranAddendumsMC>
<TranAddendumsAMEX></TranAddendumsAMEX>
<TranAddendumsJCB></TranAddendumsJCB>
<OrderExpirationPeriod></OrderExpirationPeriod>
<OrigAmount></OrigAmount>
<OrigCurrency></OrigCurrency>
</AddParams>
<Fee></Fee>
</Order>
</Request>
</TKKPG>
"
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.ssl_version = :TLSv1_2
http.cert = OpenSSL::X509::Certificate.new(File.read(File.join(Rails.root, "/crt/example.com.crt")))
http.key = OpenSSL::PKey::RSA.new(File.read(File.join(Rails.root, "/crt/example.com.key")))
req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/xml'})
@res = http.request(req, xml)
Reference.
HTTP library for Ruby with HTTPS, SSL Client Certificate and Keep-Alive support?
Related Topics
Use Ruby Array for a JavaScript Array in Erb. Escaping Quotes
Problem Installing SQLite3-Ruby!
Session Not Destroyed When Closing Browser - Railstutorial.Org
Ruby on Rails Source Code Security/Obfuscation
Uploading Files in Ruby on Rails
How to Do Ruby Object Serialization Using JSON
Scanning for Unicode Numbers in a String with \D
Ruby/Pgsql Error on Rails Start:Cannot Load Such File -- Pg_Ext (Loaderror)
Modifying the Default Hash Value
-': Nil Can't Be Coerced into Fixnum (Typeerror)
Match Sequences of Consecutive Characters in a String
Install Nokogiri 1.6.1 Under Ruby 2.0.0P353 (Rvm Based Installation) Fails (Osx Mavericks)
Can't Get to Work Cocoapods and Yosemite
Why Does Rails 4.2 + Responders Keeps Telling Me to Add Responders to the Gemfile
Generate All "Unique" Subsets of a Set (Not a Powerset)
In Ruby, What Are the Vertical Lines