I am trying to run the following code to call a webservice from ruby but get an error 'SSL not supported'.
I have httpclient 2.1.5.2 installed.
require 'soap/wsdlDriver'
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(file_name).read == ctx.current_cert.to_pem
end
is_ok
end
def test_webservice
wsdl = "https://.../service.wsdl"
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
driver.options['protocol.http.ssl_config.verify_callback'] = method(:validate_certificate)
driver.method(params)
end
could this be your problem?
http://groups.google.com/group/soap4r/browse_thread/thread/e4d87acac8fe51d5
Related
Good day!
I am trying to send POST requests to a server via ssl connection with .p12 certificate from Windows 7 with Ruby's Faraday library.
Ruby's version is ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
Faraday gem's version are: faraday (0.14.0, 0.9.2)
1) I have a folder with the following cert files:
[cert_name].crt,
[cert_name].csr,
[cert_name].key,
[cert_name].p12
2) As to the code, I have the following:
require "faraday"
require "json"
require "openssl"
data = [JSON_object]
host = 'https://[domain_name]'
url = '[string]/[string]'
p12 = OpenSSL::PKCS12.new(File.open('[path_to_folder_with_cert_files]/[cert_name].p12', "rb").read, "[password]")
key = p12.key
cert = p12.certificate
connection = Faraday::Connection.new host, :ssl => {
:client_cert => cert,
:client_key => key,
:ca_file => '[path_to_folder_with_cert_files]/[cert_name].crt',
:verify => false
}
puts response.status = connection.post do |req|
req.url(url)
req.headers['Content-Type'] = #headers["content_type"]
req.body = data
end
Response has 403 Forbidden. I have tested with no ssl connection the data, url, host parameters and the status is 200 OK.
Please help, as I have found no tutorial / question to this particular use of Ruby's Faraday and OpenSSL::PKCS12
The following worked for me:
class Gateway
def call
connection.get do |req|
req.url(url)
req.headers['Content-Type'] = 'text/xml'
req.body = data
end
end
def connection
Faraday.new(ssl: ssl) do |builder|
builder.request :retry
builder.response(:logger) unless Rails.env.test?
builder.adapter :net_http
end
end
def ssl
{
client_key: client_key,
client_cert: client_cert,
ca_file: 'CA.crt' # optional
}
end
def url
'https://...'
end
def client_key
p12.key
end
def client_cert
p12.certificate
end
def p12
OpenSSL::PKCS12.new(p12_file.read, p12_password)
end
def p12_file
File.open('<path-to-p12-file>', 'rb')
end
def p12_password
'password' # if password protected
end
end
And the usage:
puts Gateway.new.call.body
I am trying to fetch files from a server using FTPS. I'm able to authenticate but when I try to list/fetch the files, I get a "521 Data connections must be encrypted". Is the Net::FTP module capable of this, and how would I accomplish it?
I modified Net::FTPTLS into my own class because I needed to store a self-signed cert.
require 'socket'
require 'openssl'
require 'net/ftp'
module MP
class FTPS < Net::FTP
def connect(host, port=FTP_PORT)
#hostname = host
super
end
def login(user = "anonymous", passwd = nil, cert_file = nil, acct = nil)
store = OpenSSL::X509::Store.new
if cert_file == nil
store.set_default_paths
else
certraw = File.read(cert_file)
cert = OpenSSL::X509::Certificate.new(certraw)
store.add_cert(cert)
end
ctx = OpenSSL::SSL::SSLContext.new('SSLv23')
ctx.cert_store = store
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.key = nil
ctx.cert = cert
voidcmd("AUTH TLS")
#sock = OpenSSL::SSL::SSLSocket.new(#sock, ctx)
#sock.connect
##sock.post_connection_check(#hostname)
super(user, passwd, acct)
voidcmd("PBSZ 0")
end
end
end
And here's the snippet for trying to fetch the files:
def get_ftpclient(host)
FTPS::new(host)
end
def check_for_files
#ftp = get_ftpclient(#host)
#ftp.passive = true
#ftp.login(#user_name, #password, #cert_file)
#ftp.chdir(#remote_dir)
files = #ftp.nlst
files
end
It fails on the nlst.
Edit: I tried adding voidcmd("PROT P") to the end of the login function but it just hangs for a while, then I eventually get:
IOError: Unsupported record version Unknown-48.48
___BEGIN BACKTRACE___
org/jruby/ext/openssl/SSLSocket.java:564:in `sysread'
/opt/jruby/lib/ruby/gems/1.8/gems/jruby-openssl-0.7.6.1/lib/1.8/openssl/buffering.rb:36:in `fill_rbuff'
/opt/jruby/lib/ruby/gems/1.8/gems/jruby-openssl-0.7.6.1/lib/1.8/openssl/buffering.rb:159:in `eof?'
/opt/jruby/lib/ruby/gems/1.8/gems/jruby-openssl-0.7.6.1/lib/1.8/openssl/buffering.rb:134:in `readline'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:211:in `getline'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:221:in `getmultiline'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:235:in `getresp'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:251:in `voidresp'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:436:in `retrlines'
/opt/jruby/lib/ruby/1.8/monitor.rb:191:in `mon_synchronize'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:422:in `retrlines'
/opt/jruby/lib/ruby/1.8/net/ftp.rb:612:in `nlst'
... etc
I realize this is an old question, but I stumbled upon it while researching FTPS ruby gems.
No. net::FTP does not, on its own, support FTPS.
I highly recommend double-bag-ftps.
Provides a child class of Net::FTP to support implicit and explicit FTPS.
Version 0.1.1 has been working beautifully for me running daily for the past year.
Now I try to connect to my socket cretaed by unicorn with this code
require 'socket'
def foo
socket = UNIXSocket.new("path_to_socket/tmp/unicorn.sock")
data = "GET /time HTTP/1.1\n"
data << "Connection: Close\n"
data << "User-Agent: Mozilla/5.0\n"
data << "Accept: */*\n"
data << "Content-Type: application/x-www-form-urlencoded\n"
data << "\n\r\n\r"
socket.puts(data)
while(line = socket.gets) do
puts line
end
end
foo
But always get a "HTTP/1.1 400 Bad Request"
Please, can any body say what I'm do wrong???
Use net/http...
require "net/http"
require "socket"
sock = Net::BufferedIO.new(UNIXSocket.new("path_to_socket/tmp/unicorn.sock"))
request = Net::HTTP::Get.new("/time")
request.exec(sock, "1.1", "/time")
begin
response = Net::HTTPResponse.read_new(sock)
end while response.kind_of?(Net::HTTPContinue)
response.reading_body(sock, request.response_body_permitted?) { }
response.body
response.code
This is very helpful but please note that the Net::HTTP#exec method is marked for internal use only. Likely because it doesn't do resource management, etc.
The following work adapts the suggested strategy to override Net::HTTP#connect (to connect to a socket). I like to use the HTTParty gem for handling my HTTP requests. So the strategy here makes use of a custom ConnectionAdaptor for HTTParty. Now I can just change the ::default_params= call on my including class, to control whether we're using a Unix or a TCP/HTTP socket.
###########################################################
# net/socket_http.rb
###########################################################
module Net
# Overrides the connect method to simply connect to a unix domain socket.
class SocketHttp < HTTP
attr_reader :socket_path
# URI should be a relative URI giving the path on the HTTP server.
# socket_path is the filesystem path to the socket the server is listening to.
def initialize(uri, socket_path)
#socket_path = socket_path
super(uri)
end
# Create the socket object.
def connect
#socket = Net::BufferedIO.new UNIXSocket.new socket_path
on_connect
end
# Override to prevent errors concatenating relative URI objects.
def addr_port
File.basename(socket_path)
end
end
end
###########################################################
# sock_party.rb, a ConnectionAdapter class
###########################################################
require "net/http"
require "socket"
class SockParty < HTTParty::ConnectionAdapter
# Override the base class connection method.
# Only difference is that we'll create a Net::SocketHttp rather than a Net::HTTP.
# Relies on :socket_path in the
def connection
http = Net::SocketHttp.new(uri, options[:socket_path])
if options[:timeout] && (options[:timeout].is_a?(Integer) || options[:timeout].is_a?(Float))
http.open_timeout = options[:timeout]
http.read_timeout = options[:timeout]
end
if options[:debug_output]
http.set_debug_output(options[:debug_output])
end
if options[:ciphers]
http.ciphers = options[:ciphers]
end
return http
end
end
###########################################################
# class MockSockParty, a really *nix-y HTTParty
###########################################################
class MockSockParty
include HTTParty
self.default_options = {connection_adapter: SockParty, socket_path: '/tmp/thin.sock'}
def party_hard
self.class.get('/client').body
end
end
###########################################################
# sock_party_spec.rb
###########################################################
require 'spec_helper'
describe SockParty do
it "should party until its socks fall off." do
puts MockSockParty.new.party_hard
end
end
Trying to establish a connection from a module in Rails and get no connection to server. I have tested the same code outside Rails and it works fine.
require 'rubygems'
require 'net-ldap'
module Foo
module Bar
class User
attr_reader :ldap_connection
def initialize
#ldap = Net::LDAP.new(:host => "<ip-number>", :port => 389)
#treebase = "ou=People, dc=foo, dc=bar"
username = "cn=Manager"
password = "password"
#ldap.auth username, password
begin
if #ldap.bind
#ldap_connection = true
else
#ldap_connection = false
end
rescue Net::LDAP::LdapError
#ldap_connection = false
end
end
end
end
end
Getting Net::LDAP::LdapError: no connection to server exception.
I found a solution/workaround for my problem with auto-loading in Rails. Added a new initializer to ensure that all Ruby files under lib/ get required:
Added config/initializers/require_files_in_lib.rb with this code
Dir[Rails.root + 'lib/**/*.rb'].each do |file|
require file
end
Read more about the workaround: Rails 3 library not loading until require
My Omniauth integration works on local development but fails for google on staging.
require 'omniauth/openid'
require 'openid/store/memcache'
Rails.application.config.middleware.use OmniAuth::Builder do
OmniAuth.config.full_host = "http://xx.xx.xxx/"
# dedicated openid
provider :open_id, OpenID::Store::Memcache.new(Dalli::Client.new), :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
end
I get a this error message:
Started GET "/auth/failure?message=invalid_credentials" for 58.71.19.178 at 2011-12-01 02:22:20 +0000
Processing by ErrorsController#routing as HTML
Parameters: {"message"=>"invalid_credentials", "a"=>"auth/failure"}
Rendered public/404.html (0.1ms)
Completed 404 Not Found in 1ms (Views: 0.6ms | ActiveRecord: 0.0ms)
Also the ip in for is not the same in my OmniAuth.config.full_host maybe that could be causing the issue?
The culprit was that apache sending and returning on different ips
This monkey patch fixed the issue.
module OmniAuth
module Strategies
# OmniAuth strategy for connecting via OpenID. This allows for connection
# to a wide variety of sites, some of which are listed [on the OpenID website](http://openid.net/get-an-openid/).
class OpenID
protected
def callback_url
uri = URI.parse(request.url)
uri.path += '/callback'
# by KirylP: to overcome hosting subdomain forwarding to rails port
uri.port = '' if request.env.has_key? 'HTTP_X_FORWARDED_SERVER'
uri.to_s
end
end
end
end
module Rack
class OpenID
SERVER_PORT_TO_AVOID = 12002
private
def realm_url(req)
url = req.scheme + "://"
url << req.host
scheme, port = req.scheme, req.port
if scheme == "https" && port != 443 ||
scheme == "http" && port != 80
url << ":#{port}" if port != SERVER_PORT_TO_AVOID # KirylP
end
url
end
end
end
module OpenID
class Consumer
def complete(query, current_url)
message = Message.from_post_args(query)
current_url.sub!(":#{Rack::OpenID::SERVER_PORT_TO_AVOID}", '') # KirylP
mode = message.get_arg(OPENID_NS, 'mode', 'invalid')
begin
meth = method('complete_' + mode)
rescue NameError
meth = method(:complete_invalid)
end
response = meth.call(message, current_url)
cleanup_last_requested_endpoint
if [SUCCESS, CANCEL].member?(response.status)
cleanup_session
end
return response
end
end
end
I had a similar problem. Seems like your google authentication fails (can be for different reasons - invalid credentials, or user denied access), therefore you receive callback to /auth/failure -- and then you get 404.
Did you implement a route for /auth/failure in your routes.rb? In my current project:
in routes.rb
match '/auth/failure', :to => 'sessions#failure'
in sessions_controller
def failure
redirect_to session[:return_uri] || root_path, alert: "Sorry, we were not able to authenticate you using your chosen sign on method"
end