Consume SSL protected Web Services with soap4r
After hours of google this deserves a blog post. I did not find a clear example about this, so I am writing one.
I had the need to call a .NET Web Service over https with mutual authentication and basic authentication.
First of all I installed the soap4r gem, then the httpclient gem (because that one supports basic authentication).
Then I made a folder called “certs” with all the certificates and key files I had:
- ca.cer – the certificate of the certification authority that signed the server certificate
- server.cer – the certificate of the server (signed by the guys who own ca.cer)
- client.cer – the client certificate I need to send along the request to get the content
- client.key – the key file for the client certificate
That’s all the certs and key files I needed.
Now it was time to try to get the wsdl:
This worked.
Time to try soap4r:
To tell soap4r that you want basic authentication and where the certificate files are, you need to create a soap/property file with the following content:
This file is loaded at startup (you can find other options in soap/lib/soap/httpconfigloader.rb), and configures the ssl and basic auth stuff for soap4r.
I had the need to call a .NET Web Service over https with mutual authentication and basic authentication.
First of all I installed the soap4r gem, then the httpclient gem (because that one supports basic authentication).
Then I made a folder called “certs” with all the certificates and key files I had:
- ca.cer – the certificate of the certification authority that signed the server certificate
- server.cer – the certificate of the server (signed by the guys who own ca.cer)
- client.cer – the client certificate I need to send along the request to get the content
- client.key – the key file for the client certificate
That’s all the certs and key files I needed.
Now it was time to try to get the wsdl:
require 'http-access2'
url = 'https://secure.example.com/web_service/wsdl'
client = HTTPAccess2::Client.new()
client.ssl_config.set_client_cert_file('certs/client.cer', 'certs/client.key')
client.ssl_config.set_trust_ca('certs/ca.cer')
client.set_basic_auth(url, 'username', 'password')
puts client.get(url).content
This worked.
Time to try soap4r:
require 'rubygems' #if you installed httpclient with rubygems you need this
require 'soap/wsdlDriver'
#this validates the server certificate
#so you can be sure that the server you are
#sending data to is the server you have the
#certificate of in certs/server.cer
def validate_certificate(is_ok, ctx)
cert = ctx.current_cert
unless (cert.subject.to_s == cert.issuer.to_s) #check the server certificate only
is_ok &&= File.open('certs/server.cer').read == ctx.current_cert.to_pem
end
is_ok
end
wsdl = 'https://secure.example.com/web_service/wsdl'
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
#driver.wiredump_dev = STDOUT
driver.options['protocol.http.ssl_config.verify_callback'] = method(:validate_certificate)
results = driver.web_service_method(arg1, arg2)
p results
To tell soap4r that you want basic authentication and where the certificate files are, you need to create a soap/property file with the following content:
client.protocol.http.basic_auth.1.url = https://secure.example.com/web_service/wsdl client.protocol.http.basic_auth.1.userid = username client.protocol.http.basic_auth.1.password = password client.protocol.http.ssl_config.client_cert = certs/client.cer client.protocol.http.ssl_config.client_key = certs/client.key client.protocol.http.ssl_config.ca_file = certs/ca.cer client.protocol.http.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER client.protocol.http.ssl_config.ciphers = ALL client.protocol.http.ssl_config.verify_depth = 1
This file is loaded at startup (you can find other options in soap/lib/soap/httpconfigloader.rb), and configures the ssl and basic auth stuff for soap4r.