How to open secure connection in ruby - ruby

I am quite new to ruby here i am opening a secure connection for amazon s3 in ruby.
here i write a simple method as follows when you call this method it establishes a connection but i think it is not as secure
def delete_file(path, &block)
AWS::S3::Base.establish_connection!(:access_key_id => $key, :secret_access_key => $skey) #here propery connection done
AWS::S3::S3Object.delete path, $bkt #here file gets deleted
yield true
end
then i searched and i found start_tls method of eventmachine from
http://eventmachine.rubyforge.org/EventMachine/Connection.html#start_tls-instance_method

You should be able to use :use_ssl => true as written in the manuals:
You can specify whether the url should go over SSL with the
:use_ssl option:
# Url will use https protocol
S3Object.url_for('beluga_baby.jpg', 'marcel', :use_ssl => true)

Related

enforcing Faraday adapter :typhoeus to use HTTP/2 for requests

How to enforce Faraday adapter typhoeus to use HTTP/2 for requests to servers which supported HTTP/2?
I have tested this over service https://http2.pro/doc/api and result was like this:
body="{\"http2\":1,\"protocol\":\"HTTP\\/2.0\",\"push\":0,\"user_agent\":\"Faraday v0.12.2\"}",
\"http2\":1, what means that HTTP/2 not used for request!
There are two things at play here. The first is that the remote API is lying to you in the response body. Their documentation says:
http2: Possible values are 0 (HTTP/2 was used) and 1 (HTTP/2 was not used).
Even though the response body shows 'http2': 1 indicating that HTTP2 was not used, it is being used. You can most easily confirm this using Chrome's dev tools:
So once we know that the API is lying in the response body, how can we independently confirm that Typhoeus is using HTTP2?
(this answer assumes you are using pry as your REPL, not IRB)
First let's confirm that Typhoeus alone will use HTTP2:
require 'typhoeus'
response = Typhoeus.get("https://http2.pro/api/v1", http_version: :httpv2_0)
response.class
=> Typhoeus::Response < Object
response.body
=> "{\"http2\":1,\"protocol\":\"HTTP\\/2.0\",\"push\":0,\"user_agent\":\"Typhoeus - https:\\/\\/github.com\\/typhoeus\\/typhoeus\"}" # this is the lying API response
response.http_version
=> "2" # this is what Typhoeus tells us was actually used
Now let's test it in Faraday:
require 'faraday'
require 'typhoeus'
require 'typhoeus/adapters/faraday'
conn = Faraday.new do |faraday|
faraday.adapter :typhoeus, http_version: :httpv2_0
end
response = conn.get("https://http2.pro/api/v1")
response.body
=> "{\"http2\":1,\"protocol\":\"HTTP\\/2.0\",\"push\":0,\"user_agent\":\"Faraday v0.17.0\"}" # again we get the lying API response
But how can we confirm it was HTTP2? This doesn't work:
response.http_version
NoMethodError: undefined method `http_version' for #<Faraday::Response:0x00007f99935519a8>
Because response isn't a Typhoeus::Response object, it's a Faraday object:
response.class
=> Faraday::Response < Object
So we need to get into the gem itself to figure out where it's creating the Typhoeus::Response object so we can call .http_version on it manually and confirm it's using the protocol we expect. As it turns out, that's right here.
Let's take the easy route and stick binding.pry into our local copy of the gem (you'll need to restart pry to pick up the changes to the gem):
def typhoeus_request(env)
opts = {
:method => env[:method],
:body => env[:body],
:headers => env[:request_headers]
}.merge(#adapter_options)
binding.pry
::Typhoeus::Request.new(env[:url].to_s, opts)
end
Then re-run the request:
require 'faraday'
require 'typhoeus'
require 'typhoeus/adapters/faraday'
conn = Faraday.new do |faraday|
faraday.adapter :typhoeus, http_version: :httpv2_0
end
response = conn.get("https://http2.pro/api/v1")
And you'll see:
Frame number: 0/3
From: /Users/foo/.rvm/gems/ruby-2.6.3/gems/typhoeus-1.3.1/lib/typhoeus/adapters/faraday.rb # line 127 Faraday::Adapter::Typhoeus#typhoeus_request:
120: def typhoeus_request(env)
121: opts = {
122: :method => env[:method],
123: :body => env[:body],
124: :headers => env[:request_headers]
125: }.merge(#adapter_options)
126: binding.pry
=> 127: ::Typhoeus::Request.new(env[:url].to_s, opts)
128: end
Now enter:
response = ::Typhoeus::Request.new(env[:url].to_s, opts).run
And confirm it's a Typhoeus::Response object:
response.class
=> Typhoeus::Response < Object
And confirm it's using HTTP2:
response.http_version
=> "2"
And confirm the API response body is a dirty liar:
response.body
=> "{\"http2\":1,\"protocol\":\"HTTP\\/2.0\",\"push\":0,\"user_agent\":\"Faraday v0.17.0\"}"
And that's how you use Typhoeus as a Faraday adapter to make an HTTP2 request.

How to connect to FTP via SOCKS5 proxy with Ruby?

I'm trying to connect to FTP via SOCKS5 proxy using ruby's library Net::FTP. Documentation says to set env variable SOCKS_SERVER in order to connect through proxy (http://ruby-doc.org/stdlib-2.0.0/libdoc/net/ftp/rdoc/Net/FTP.html#method-i-connect), but it seems like it does not work.
Code I'm running is this:
irb(main):054:0> ftp = Net::FTP.new
=> #<Net::FTP:0x007efd08c73768 #mon_owner=nil, #mon_count=0, #mon_mutex=#<Thread::Mutex:0x007efd08c73718>, #binary=true, #passive=true, #debug_mode=false, #resume=false, #sock=#<Net::FTP::NullSocket:0x007efd08c736f0>, #logged_in=false, #open_timeout=nil, #read_timeout=60>
irb(main):056:0> ENV['SOCKS_SERVER'] = 'host:port'
=> "host:port"
irb(main):055:0> ftp.connect('test.rebex.net')
=> nil
irb(main):057:0> ftp.login('demo', 'password')
=> true
irb(main):058:0> ftp.ls
=> ["10-27-15 03:46PM <DIR> pub", "04-08-14 03:09PM 403 readme.txt"]
When I look to proxy logs I can not see any requests going through.
What I'm doing wrong or does anybody have an example how to achieve that?
If your on Windows computer you'll need to use dress_socks gem and Monkeypath:
$socks_server = '127.0.0.1'
$socks_port = '9090'
require 'dress_socks'
class Net::FTP
def open_socket(host, port) # :nodoc:
# puts "opening socket #{#host}:#{port}"
return DressSocks::Socket.new(#host, port,
socks_server: $socks_server, socks_port: $socks_port)
end
end

URI.parse returns nil port for sftp and ftps

When I try to parse the following URLs, URI.parse returns nil for the port:
require 'uri'
url = "ftp://example.com"
puts URI.parse(url).port
# => 21
url = "sftp://example.com"
puts URI.parse(url).port
# => nil
url = "ftps://example.com"
puts URI.parse(url).port
# => nil
Can someone explain why this works for ftp, http and https but not for sftp and ftps?
Because sftp and ftps aren't sepcified, neither the ports they use.
You can check this in the documentation of URI. Look at the namespace.:
http://ruby-doc.org/stdlib-2.1.0/libdoc/uri/rdoc/URI.html
You will find ftp, http, https but no sftp or ftps.
Unrecognized URI's like these will be of type -> URI::Generic
By looking into their documentation you will see that they have a default port of nil.:
http://ruby-doc.org/stdlib-2.1.0/libdoc/uri/rdoc/URI/Generic.html
You can try this out yourself by running this:
puts URI.parse("sftp://example.com").class
They are not supported by default in Ruby -
p URI.scheme_list
#=> {"FTP"=>URI::FTP,
"HTTP"=>URI::HTTP,
"HTTPS"=>URI::HTTPS,
"LDAP"=>URI::LDAP,
"LDAPS"=>URI::LDAPS,
"MAILTO"=>URI::MailTo}
the sftp and ftps are not represented by any Ruby class. Hence, default port for them will not be picked automatically.

How do I process a URL in ruby to extract the component parts (scheme, username, password, host, etc)?

I'm trying create a program using ruby (and Net::SSH) to connect to servers and perform some tasks. The details of the server are to be provided as something like:
ssh://user:pass#host:port (for a host that does not yet have SSH keys)
or
user#host
Net::SSH expects the following format:
Net::SSH.start('host', 'user', :password => "password")
Is there are gem/stdlib that can process the URL into this format? Or a simple regex that can match the different parts?
Note: I'm aware of, and use, capistrano but in this case I need lower level control.
Both URI and Addressable::URI can parse URLs and let you break them down into their components.
URI is included in Ruby's Standard Library, which is nice, but Addressable::URI has more features, and is what I use when I have to do a lot of work on URLs.
require 'addressable/uri'
uri = Addressable::URI.parse('ssh://user:pass#www.example.com:81')
uri.host # => "www.example.com"
uri.user # => "user"
uri.password # => "pass"
uri.scheme # => "ssh"
uri.port # => 81
require 'uri'
uri = URI.parse('ssh://user:pass#www.example.com:81')
uri.host # => "www.example.com"
uri.user # => "user"
uri.password # => "pass"
uri.scheme # => "ssh"
uri.port # => 81

Ruby SOAP SSL Woes

I have a SOAP client in Ruby that I'm trying to get working with a Ruby SOAP server, to no avail. The client works fine over SSL with a Python SOAP server, but not with the Ruby version. Here's what the server looks like:
require 'soap/rpc/standaloneServer'
require 'soap/rpc/driver'
require 'rubygems'
require 'httpclient'
def cert(filename)
OpenSSL::X509::Certificate.new(File.open("path to cert.cert") { |f|
f.read
})
end
def key(filename)
OpenSSL::PKey::RSA.new(File.open("path to rsaprivate.key") { |f|
f.read
})
end
class Server < SOAP::RPC::HTTPServer
~code snipped for readability~
end
server = Server.new(:BindAddress => HelperFunctions.local_ip, :Port => 1234, :SSLCertificate => cert("path to cert"), :SSLPrivateKey => key("path to rsa private key"))
new_thread = Thread.new { server.start }
I've trimmed some of the code out for readability's sake (e.g., I have some methods in there I expose) and it works fine with SSL off. But when the client tries to connect, it sees this:
warning: peer certificate won't be verified in this SSL session
/usr/lib/ruby/1.8/net/http.rb:567: warning: using default DH parameters.
/usr/lib/ruby/1.8/net/http.rb:586:in `connect': unknown protocol (OpenSSL::SSL::SSLError)
I tried taking some advice from this post and now I see this message:
/usr/lib/ruby/1.8/soap/httpconfigloader.rb:64:in `set_ssl_config': SSL not supported (NotImplementedError)
Any ideas on how to fix this would be greatly appreciated.
Arg. I was trying to follow along this link and it turns out I was missing a simple include statement:
require 'webrick/https'
That, combined with the help from the link in the original question solves the problem. Hopefully this saves someone else down the line an hour of grief :)
"SSL not supported" can be caused by not having httpclient installed.
Me too.. and don't forget to put the :SSLEnable => true spend couple of hours figuring that out...
server = Server.new(:BindAddress => HelperFunctions.local_ip, :Port => 1234, :SSLEnable => true, :SSLCertificate => cert("path to cert"), :SSLPrivateKey => key("path to rsa private key"))

Resources