Savon - Program crash at "Error" Response - ruby

I made a simple SOAP-Request using Savon.
require 'savon'
client = Savon.client(:wsdl => 'https://url?wsdl', :ssl_verify_mode => :none,
wsse_auth: ["username", "password"],pretty_print_xml: true)
trackingnumber = 'anyNumber'
response = client.call(:shipment_status) do
message(Id: trackingnumber)
end
puts response
The problem is, if I get a "Error-Response", for instance if the trackingnumber don`t exists, then my program is crashing. But I dont want the program to crash, I want to keep the response. Here is the error:
c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/response.rb:85:in `raise_soap_and_http_errors!': (soap:Server) Fault occurred while processing. (Savon::SOAPFault)
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/response.rb:14:in `initialize'
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/operation.rb:64:in `new'
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/operation.rb:64:in `create_response'
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/operation.rb:55:in `call'
from c:/Ruby200/lib/ruby/gems/2.0.0/gems/savon-2.3.2/lib/savon/client.rb:36:in `call'
Is there a solution for this problem?

I think your syntax is off. Do you use Savon 2.x?
You should guard the call with an Exception handler.
require 'savon'
client = Savon.client(
:wsdl => 'https://url?wsdl',
:ssl_verify_mode => :none,
wsse_auth: ["username", "password"],
:raise_errors => true, # false if you don't want to see exceptions
pretty_print_xml: true)
trackingnumber = 'anyNumber'
begin
response = client.call(
:shipment_status,
:messageId => {:trackingnumber => trackingnumber}
)
rescue Savon::Error => soap_fault
print "Error: #{soap_fault}\n"
end
puts response
You can also set the parameter :raise_errors to false when creating your client. then you have to handle the return values accordingly.

Related

Ruby: hitting read_timeout even when changed

From my Ruby code il make a call to a API.
On the testsystem with few data it works without a flaw.
On the Productive System it works too, but only if not much data is transmitted. If its too much data il get:
/usr/lib/ruby/2.3.0/net/protocol.rb:158:in rbuf_fill': Net::ReadTimeout (Net::ReadTimeout)
from /usr/lib/ruby/2.3.0/net/protocol.rb:136:inreaduntil'
from /usr/lib/ruby/2.3.0/net/protocol.rb:146:in readline'
from /usr/lib/ruby/2.3.0/net/http/response.rb:40:inread_status_line'
from /usr/lib/ruby/2.3.0/net/http/response.rb:29:in read_new'
from /usr/lib/ruby/2.3.0/net/http.rb:1437:inblock in transport_request'
from /usr/lib/ruby/2.3.0/net/http.rb:1434:in catch'
from /usr/lib/ruby/2.3.0/net/http.rb:1434:intransport_request'
from /usr/lib/ruby/2.3.0/net/http.rb:1407:in `request'
the relevant part in the code seems to be:
http = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https', :verify_mode => OpenSSL::SSL::VERIFY_NONE, :read_timeout => #timeout)
i bumped the #timeout to 900 and id didnt work eater.
Any ideas how i can get that to work or how i can debug that issue?

How to pass in values and headers via Ruby basic authentication?

I'm trying to pass in certain values and headers via Ruby but not sure how to do it. What I have so far:
uri = URI.parse('http://jira.test.local/rest/zapi/latest/execution')
req = Net::HTTP::Get.new(uri)
req.basic_auth 'userid', 'password'
res = Net::HTTP.start(uri.hostname, uri.port) {|http| http.request(req)}
puts res.body
values = "{\n \"issueId\": 32640,\n \"versionId\": \"11163\",\n \"cycleId\": \"5\",\n \"projectId\": 10460\n,\n \"status\": \"1\"}"
headers = {:content_type => "application/json"}
Net::HTTP.start(uri.hostname, uri.port) do | http |
response = http.post(req, values)
puts response.body
end
I'm getting this error right now:
{"status":{"1":{"id":1,"color":"#75B000","description":"Test was executed and passed successfully.","name":"PASS"},"2":{"id":2,"color":"#CC3300","description":"Test was executed and failed.","name":"FAIL"},"3":{"id":3,"color":"#F2B000","description":"Test execution is a work-in-progress.","name":"WIP"},"4":{"id":4,"color":"#6693B0","description":"The test execution of this test was blocked for some reason.","name":"BLOCKED"},"-1":{"id":-1,"color":"#A0A0A0","description":"The test has not yet been executed.","name":"UNEXECUTED"}},"executions":[],"currentlySelectedExecutionId":""}
undefined method `empty?' for #<Net::HTTP::Get GET> (NoMethodError)
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http/generic_request.rb:27:in `initialize'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http/request.rb:14:in `initialize'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:1390:in `new'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:1390:in `send_entity'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:1179:in `post'
./features/step_definitions/zapi_farooq.rb:32:in `block (2 levels) in <top (required)>'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:852:in `start'
/Users/fyousuf/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/net/http.rb:582:in `start'
./features/step_definitions/zapi_farooq.rb:31:in `/^I test zapi update$/'
features/zapi_farooq.feature:4:in `* I test zapi update'
The first line of the output is good, it's giving me the proper outpul from the res.body, but after that is the error.
Summary: I want to go to the uri, authenticate with creds and post with the values provided and with the proper headers (all using Ruby).
I'm trying to create a new execution as per this API: http://docs.getzephyr.apiary.io/#executionresourceapis (Create a new Execution)
Playing around I got it to work with:
values = "{\n \"status\": 2\n}"
headers = {:content_type => "application/json"}
response = RestClient::Resource.new 'http://jira.test.local/rest/zapi/latest/execution/343/execute', 'username', 'password'
response.put values, headers
puts response
puts response.body
Gives output of:
http://jira.test.local/rest/zapi/latest/execution/343/execute
<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body></body></html>
Also it changes the value of the issue in Jira (intended goal).
I just used RestClient b/c the original docs (http://docs.getzephyr.apiary.io/#executionresourceapis) were using it and got some help here too: https://github.com/rest-client/rest-client

Why Am I getting a NoMethodError when using the google API to run a query against google Big Query?

I'm trying to run a Query against Google Big Query, using the Ruby API.
This is my first project with Ruby and I'm still learning the language.
This is also my first project using the Google API.
ENVIORNMENT:
Windows 7
Ruby 1.9
Faraday 0.90
Goolge API - Service Account Authentication
My Code runs without giving any warnings or error messages through:
#client.authorization.fetch_access_token!
doc = File.read('bigQueryAPI.json')
#bigQuery = #client.register_discovery_document('bigquery', 'v2', doc)
NOTE: #bigQuery is loaded from a file because when I try to load #bigquery with
#bigquery = #client.discovered_api('bigquery', 'v2')
I get Google::APIClient::ClientError: Not Found and inspect only prints
#<Google::APIClient::API:0x17c94cc ID:bigquery:v2>
However If I save the Big Query API as a text file from
https://www.googleapis.com/discovery/v1/apis/bigquery/v2/rest
and then load it as a text file with
doc = File.read('bigQueryAPI.json')
#bigQuery = #client.register_discovery_document('bigquery', 'v2', doc)
then #bigQuery.inspect actually returns something useful.
#bigQuery.inspect output.
However, When I try to actually run a query, like so:
result = #client.execute!(
:api_method => #bigQuery.batch_path.query,
:body_object => { "query" => "SELECT count(DISTINCT repository_name) as repository_total, " +
"count(payload_commit) as commits_total, " +
"count(DISTINCT repository_name) / count(payload_commit) as average, " +
"FROM [githubarchive:github.timeline]" }, #,
:parameters => { "projectId" => #project_id })
I get the following error:
NoMethodError: undefined method `query_values' for nil:NilClass
Here's the Full Stacktrace of the error:
1) Error:
test_averages(Test_GitHub_Archive):
NoMethodError: undefined method `query_values' for nil:NilClass
C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client/request.rb:145:in `uri='
C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client/request.rb:101:in `initialize'
C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client.rb:518:in `new'
C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client.rb:518:in `generate_request'
C:/Ruby193/lib/ruby/gems/1.9.1/gems/google-api-client-0.7.1/lib/google/api_client.rb:583:in `execute!'
C:/Users/tfburton/Documents/private/ProjectSuggestor/RubyStats/GitHub_Archive.rb:39:in `get_averages'
C:/Users/tfburton/Documents/private/ProjectSuggestor/RubyStats/TestSpec/test_GitHub_Archive.rb:26:in `test_averages'
Here is the results for #client.inspect
NOTE: I would have pasted here, but my post ended over the length limit.
After doing some digging. It looks like I'm not passing the proper #bigQuery prameter to get the query function.
Looking at the dump for #bigQuery.inspect I need to pass the method at line 751.
However I can't seem to figure out how to pass that method.
If you strip out the rest of the inspect output the "path" looks like this:
{ "resources => { "jobs" => { "methods" => { "query"
I've tried #bigQuery.Jobs.query and that results in an error stating that #bigQuery.Jobs doesn't exist.
So am I creating #bigQuery correctly?
Why doesn't #bigQuery.Jobs.query work?
Here's how I got it to work with the bigquery.jobs.query method, which is probably what you need.
I had to set OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE because otherwise the authorization process would fail miserably, but that might be specific to min Win7/MgitSys environment. In any case, this specific line is not safe in prod.
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/installed_app'
require 'google/api_client/auth/file_storage'
require 'openssl'
require 'json'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
# Initialize the client.
client = Google::APIClient.new(
:application_name => 'Example Ruby application',
:application_version => '1.0.0'
)
CREDENTIAL_STORE_FILE = "#{$0}-oauth2.json"
file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
# Initialize Google+ API. Note this will make a request to the
# discovery service every time, so be sure to use serialization
# in your production code. Check the samples for more details.
#bigQuery = client.discovered_api('bigquery', 'v2')
# Load client secrets from your client_secrets.json.
client_secrets = Google::APIClient::ClientSecrets.load
file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
if file_storage.authorization.nil?
client_secrets = Google::APIClient::ClientSecrets.load
# The InstalledAppFlow is a helper class to handle the OAuth 2.0 installed
# application flow, which ties in with FileStorage to store credentials
# between runs.
flow = Google::APIClient::InstalledAppFlow.new(
:client_id => client_secrets.client_id,
:client_secret => client_secrets.client_secret,
:scope => ['https://www.googleapis.com/auth/cloud-platform','https://www.googleapis.com/auth/bigquery']
)
client.authorization = flow.authorize(file_storage)
else
client.authorization = file_storage.authorization
end
puts "authorized, requesting"
# Make an API call.
result = client.execute!(
:api_method => #bigQuery.jobs.query,
:body_object => { "query" => "SELECT count(DISTINCT repository_name) as repository_total, " +
"count(payload_commit) as commits_total, " +
"count(DISTINCT repository_name) / count(payload_commit) as average, " +
"FROM [githubarchive:github.timeline]" }, #,
:parameters => { "projectId" => "845227657643" })
puts JSON.dump result.data

How to handle exceptions with Ruby Rest-Client

I recently switched from Ruby's Net:HTTP class to rest-client 1.6.7.
I find it a lot easier to form requests, but unlike Net:HTTP request, when rest-client gets anything other than a 200, the request dies. I've tried putting a breakpoint directly after the RestClient.get, and it never gets hit - so I'm doing something wrong.
def get_member_using_card
resource = "#{#settings_app_uri}api/v1/card/#{self.member_card_num}?token=#{#settings.api_key}"
response = RestClient.get resource
if response.code == 200
card = JSON.parse(response.body)
self.customer_id = card['card']['customer_id']
else
return 0
end
end
Which results in this stacktrace:
RestClient::ResourceNotFound - 404 Resource Not Found:
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/abstr
act_response.rb:48:in `return!'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:230:in `process_result'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:178:in `block in transmit'
/Users/tim/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/http.rb:627:in `start'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:172:in `transmit'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:64:in `execute'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient/reque
st.rb:33:in `execute'
/Users/tim/.rvm/gems/ruby-1.9.2-p290/gems/rest-client-1.6.7/lib/restclient.rb:68
:in `get'
Can someone tell me how to properly evaluate the response code and keep this exception from happening...?
See heading Exceptions on http://rubydoc.info/gems/rest-client/
for results code between 200 and 207 a RestClient::Response will be returned
for results code 301, 302 or 307 the redirection will be followed if the request is a get or a head
for result code 303 the redirection will be followed and the request transformed into a get
for other cases a RestClient::Exception holding the Response will be raised, a specific exception class will be thrown for know error codes
RestClient.get 'http://example.com/resource'
➔ RestClient::ResourceNotFound: RestClient::ResourceNotFound`
begin
RestClient.get 'http://example.com/resource'
rescue => e
e.response
end
➔ 404 Resource Not Found | text/html 282 bytes
Also in the same documentation #wich pointed to, you can pass a block to RestClient.get such that it will not throw an exception on non-200 response codes:
# Don't raise exceptions but return the response
RestClient.get('http://example.com/resource'){|response, request, result| response }
See the "Result Handling" section from the documentation.
rescue RestClient::ExceptionWithResponse => err
There are several errors that could happen, specific exception types like Errno::EHOSTUNREACH or the more generic ExceptionWithResponse. Check the readme for more info.
I believe the best way to handle exceptions of an API client is to get the original error message thrown by the API endpoint. Here is an example code to handle that with RestClient
require 'json'
def get_call
begin
standard_response = {body: nil, success: false, message: ''}
response = RestClient.get('https://example.com/api/v1/xx', headers={'Authorization' => 'AbcDef xxx'})
standard_response[:success] = true
standard_response[:body] = JSON.parse(response.body)
rescue RestClient::ExceptionWithResponse => e
http_body = JSON.parse(e.http_body) # This is the original response from the API endpoint. e.g. {'message': 'Reason for the failure'}
meaningful_error_message = http_body['message'].nil? ? e.message : http_body['message'] # if {'message': 'error message'} is the format of your API
standard_response[:message] = meaningful_error_message
end
standard_response
end
Beautiful way to handle the exceptions in rest client.
For more info do check rest-client#response-callbacks-error-handling
RestClient.get('http://example.com/resource') { |response, request, result, &block|
case response.code
when 200
p "It worked !"
response
when 423
raise SomeCustomExceptionIfYouWant
else
response.return!(&block)
end
}

Ruby/Metasploit NoMethodError undefined method `code'

Forgive me guys, new to Ruby, actually this is the first lang I have taken up, so be gentle with me ok?
Writing a mod for Metasploit which will scan a system or net for 302/500 errors on the file ScriptResource.axd which can be used in further attacks.
It starts, it runs, then crashes with error:
msf auxiliary(Scriptresource) > exploit
[*] hxxp://192.168.0.18:80 hxxp://192.168.0.18:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 302
[*] hxxp://192.168.0.5:80 hxxp://192.168.0.5:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 302
[*] hxxp://192.168.0.106:80 hxxp://192.168.0.106:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 302
[*] hxxp://192.168.0.4:80 hxxp://192.168.0.4:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 302
[*] hxxp://192.168.0.43:80 hxxp://192.168.0.43:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 500
[*] hxxp://192.168.0.236:80 hxxp://192.168.0.236:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 500
[*] hxxp://192.168.0.238:80 hxxp://192.168.0.238:80/scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1 500
[-] Auxiliary failed: NoMethodError undefined method `code' for nil:NilClass
[-] Call stack:
[-] /root/.msf4/modules/auxiliary/scanner/http/Scriptresource.rb:50:in `block in run_host'
[-] /root/.msf4/modules/auxiliary/scanner/http/Scriptresource.rb:39:in `each'
[-] /root/.msf4/modules/auxiliary/scanner/http/Scriptresource.rb:39:in `run_host'
[-] /opt/metasploit-4.2.0/msf3/lib/msf/core/auxiliary/scanner.rb:92:in `block in run'
[-] /opt/metasploit-4.2.0/msf3/lib/msf/core/thread_manager.rb:64:in `call'
[-] /opt/metasploit-4.2.0/msf3/lib/msf/core/thread_manager.rb:64:in `block in
Here is the Program:
require 'rex/proto/http'
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::WmapScanDir
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'ScriptResource Scanner',
'Description' => %q{
This module Will scan for the 302/500 response codes associated
with ScriptResource.axd on a traget machine or network. This
file is required for ASP.Net Oracle Padding attack.
},
'Author' => [ 'MyChickenNinja' ],
'License' => BSD_LICENSE,))
register_options(
[
OptString.new('PATH', [ true, "The path to identify vulnerable files", '/',
]
)
], self.class)
end
def run_host(ip)
cypher = ['scriptresource.axd?d=AAAAAAAAAAAAAAAAAAAAAA1']
conn = false
spath = datastore['PATH']
cypher.each do |cy|
queue << cy.strip
begin
crypt = cy
res = send_request_cgi({
'uri' => spath+crypt,
'method' => 'GET',
'ctype' => 'text/plain'
}, 20)
if res.code == 500 or res.code == 302
print_status("#{wmap_base_url} #{wmap_base_url}#{spath}#{crypt} #{res.code}")
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
conn = false
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
end
end
Now its referring to the "res.code". I see that, but I was under the impression that Metasploit handled res.code. Isn't this confirmed by the fact I am getting res.code output before the program crashes? So now I am at a loss... Yes I looked at other Questions on the site here but usually the answer is that they are not defined. But Metasplot defines this variable.. So... ??
As I said, I'm new to Ruby so if I can get a kinda detailed answer, I would be greatly appreciate it.
Thanks!
Figured it out.
Just needed a blank rescue to handle nil responses.

Resources