Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support OpenSSL::SSL::SSLContext#add_certificate #454

Open
dmlond opened this issue Aug 9, 2023 · 0 comments
Open

support OpenSSL::SSL::SSLContext#add_certificate #454

dmlond opened this issue Aug 9, 2023 · 0 comments

Comments

@dmlond
Copy link

dmlond commented Aug 9, 2023

we are running into an issue using a wrapper client httpi that is using httpclient under the hood. We are trying to post a request using SSL authentication to a U.S. government system. We have a single certificate with the entire certificate chain, with its key. We can make curl calls using the --cert and --key arguments pointing to these files to this website.

curl -v --cert our.chained.cer --key our.key --header "Content-Type: text/xml;charset=UTF-8" --header '{"SOAPAction"=>"\soapUrl\", "Content-Type"=>"text/xml;charset=UTF-8", "Content-Length"=>"1066"}' --data @data.xml 'https://government.url'

But calls to the same site using httpclient do not work. I would expect the following to be equivalent

require 'httpclient'

cert_file = File.read('our.chained.cer') # pem encoeded certificate file
key_file = File.read('our.key')

client = HTTPClient.new
client.ssl_config.client_cert = OpenSSL::X509::Certificate.new(cert_file)
client.ssl_config.client_key = OpenSSL::PKey::RSA.new(key_file)
client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER
client.ssl_config.ssl_version = :TLSv1_2.to_s

host = 'https://government.url'
uri = URI(host)
body = File.read('data.xml')
headers = {
    'SOAPAction' => 'soapUrl',
    'Content-Type' => 'text/xml;charset=UTF-8', 
    'Content-Length' => body.length.to_s
}
res = client.post(uri, body, headers)

But this raises an SSL error:
/usr/local/bundle/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:103:in `connect': SSL_connect returned=1 errno=0 peeraddr=52.54.170.122:443 state=error: sslv3 alert certificate unknown (OpenSSL::SSL::SSLError)

In my investigations, I was able to use net/http to make a successful request using the :extra_chain_cert method

require 'openssl'
require 'net/http'

bundle = File.read('our.chained.cer') # pem encoeded certificate file
bundle_certs = bundle.scan(/-----BEGIN CERTIFICATE-----(?:.|\n)+?-----END CERTIFICATE-----/)
client_cert = OpenSSL::X509::Certificate.new(bundle_certs[0])
intermediate_cert = OpenSSL::X509::Certificate.new(bundle_certs[1])

options = {
  use_ssl: true,
  verify_mode: OpenSSL::SSL::VERIFY_PEER,
  ssl_version: :TLSv1_2,
  cert: client_cert,
  extra_chain_cert: [intermediate_cert],
  key: OpenSSL::PKey::RSA.new(File.read('our.key'))
}

host = 'https://government.url'
uri = URI(host)
body = File.read('data.xml')
req = Net::HTTP::Post.new(uri)
req['SOAPAction'] = 'soapUrl'
req['Content-Type'] = 'text/xml;charset=UTF-8'
req['Content-Length'] = body.length
req.body = body
res = Net::HTTP.start(uri.hostname, uri.port, options) do |http|
    http.request(req)
end
puts res.response.body

Is there an equivalent in httpclient to the :extra_chain_cert option (which essentially calls OpenSSL::SSL::SSLContext.add_certificate(client_cert, client_key, [intermediate_cert])???

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant