Sunday, April 20, 2008

Writing a secure client in Ruby

WSF/Ruby provides an easy to use API to consume and deploy web services. Adding the Apache Rampart/C features, it also provides SOAP message confidentiality, integrity and authentication.
In the following four easy steps we will show how to write a secure client using WSF/Ruby.

1. Create the policy. Here we need to encrypt using the Basic256Rsa15 algorithm suite and the relavent key information should be identified using the Issuer name and the serial number of the certificate
      
policy_content = {"encrypt"=> true,
"algorithm_suite" => "Basic256Rsa15",
"security_token_reference" => "IssuerSerial"}
policy = WSPolicy.new({"security" => policy_content}

2. Create the security token. Note that the private keys and certificates need to be loaded
  
security_options = {"private_key" => pvt_key,
"receiver_certificate" => rec_cert}
security_token = WSSecurityToken.new(security_options)

3. Create options for policy and security token. Here the use_wsa=true means that the clinet MUST include WS Addressing header in the message.
  
options = {"use_wsa" => true,
"policy" => policy,
"security_token" => security_token}

4. Request from the service. For this we need to create the client.
  
client = WSClient.new(options, LOG_FILE)
res_message = client.request(payload)

The complete source code is as follows.
  
require 'wsf'
require 'rexml/document'

include WSO2::WSF
include WSO2::Util

#This is your pay load
req_payload = << XML
Hello World!
XML

begin
LOG_FILE = "security_sample.log"
ACTION = "http://php.axis2.org/samples/echoString"
END_POINT = "http://localhost:3000/encryption/encryption"

message_properties = {"to" => END_POINT,
"action" => ACTION}

#Load certificates and keys from the disk
rec_cert = WSUtil::ws_get_cert_from_file("../keys/bob_cert.cert")
pvt_key = WSUtil::ws_get_key_from_file("../keys/alice_key.pem")

#The payload or the body of the SOAP message
payload = WSMessage.new(req_payload,
nil,
message_properties)

#Create the security policy
policy_content = {"encrypt"=> true,
"algorithm_suite" => "Basic256Rsa15",
"security_token_reference" => "IssuerSerial"}

policy = WSPolicy.new({"security" => policy_content})

#Create the security token
security_options = {"private_key" => pvt_key,
"receiver_certificate" => rec_cert}

security_token = WSSecurityToken.new(security_options)

#Create option for the client
options = {"use_wsa" => true,
"policy" => policy,
"security_token" => security_token}

#Create a client instance
client = WSClient.new(options, LOG_FILE)

#Request
res_message = client.request(payload)

if not res_message.nil? then
puts "Received OM: "<< "\n" << res_message.payload_to_s << "\n\n"
puts "Client invocation SUCCESSFUL !!!"
else
puts "Client invocation FAILED !!!"
end

#If SOAP fault, print the details
rescue WSFault => wsfault
puts "Client invocation FAILED !!!\n"
puts "WSFault : "
puts wsfault.xml
puts "----------"
puts wsfault.code
puts "----------"
puts wsfault.reason
puts "----------"
puts wsfault.role
puts "----------"
puts wsfault.detail
puts "----------"

rescue => exception
puts "Client invocation FAILED !!!\n"
puts "Exception : " << exception
end

More security samples can be found here...

No comments: