Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Ciphers option to SSL Option #3

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ gem 'simplecov', '~> 0.22.0'

gem 'webmock', '~> 3.4'

gem 'rubocop', '~> 1.67.0'
less_than_ruby_v27 = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
gem 'rubocop', less_than_ruby_v27 ? '~> 1.12.0' : '~> 1.67.0'
gem 'rubocop-packaging', '~> 0.5'
gem 'rubocop-performance', '~> 1.20'
1 change: 1 addition & 0 deletions faraday-httpclient.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
spec.require_paths = ['lib']

spec.add_dependency 'httpclient', '>= 2.2'
spec.metadata['rubygems_mfa_required'] = 'true'
end
42 changes: 3 additions & 39 deletions lib/faraday/adapter/httpclient.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'faraday/httpclient/ssl_configurator'

module Faraday
class Adapter
# This class provides the main implementation for your adapter.
Expand All @@ -26,7 +28,7 @@ def build_connection(env)
end

if env[:url].scheme == 'https' && (ssl = env[:ssl])
configure_ssl @client, ssl
::Faraday::HTTPClient::SSLConfigurator.configure @client, ssl
end

configure_client @client
Expand Down Expand Up @@ -91,19 +93,6 @@ def configure_proxy(client, proxy)
client.set_proxy_auth(proxy[:user], proxy[:password])
end

# @param ssl [Hash]
def configure_ssl(client, ssl)
ssl_config = client.ssl_config
ssl_config.verify_mode = ssl_verify_mode(ssl)
ssl_config.cert_store = ssl_cert_store(ssl)

ssl_config.add_trust_ca ssl[:ca_file] if ssl[:ca_file]
ssl_config.add_trust_ca ssl[:ca_path] if ssl[:ca_path]
ssl_config.client_cert = ssl[:client_cert] if ssl[:client_cert]
ssl_config.client_key = ssl[:client_key] if ssl[:client_key]
ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
end

# @param req [Hash]
def configure_timeouts(client, req)
if (sec = request_timeout(:open, req))
Expand All @@ -122,31 +111,6 @@ def configure_timeouts(client, req)
def configure_client(client)
@config_block&.call(client)
end

# @param ssl [Hash]
# @return [OpenSSL::X509::Store]
def ssl_cert_store(ssl)
return ssl[:cert_store] if ssl[:cert_store]

# Memoize the cert store so that the same one is passed to
# HTTPClient each time, to avoid resyncing SSL sessions when
# it's changed

# Use the default cert store by default, i.e. system ca certs
@ssl_cert_store ||= OpenSSL::X509::Store.new.tap(&:set_default_paths)
end

# @param ssl [Hash]
def ssl_verify_mode(ssl)
ssl[:verify_mode] || begin
if ssl.fetch(:verify, true)
OpenSSL::SSL::VERIFY_PEER |
OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
else
OpenSSL::SSL::VERIFY_NONE
end
end
end
end
end
end
70 changes: 70 additions & 0 deletions lib/faraday/httpclient/ssl_configurator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# frozen_string_literal: true

module Faraday
module HTTPClient
# Configures SSL options for HTTPClient
class SSLConfigurator
def self.configure(client, ssl)
new(client, ssl).configure
end

def initialize(client, ssl)
@client = client
@ssl = ssl
end

def configure
ssl_config = @client.ssl_config
ssl_config.verify_mode = ssl_verify_mode
ssl_config.cert_store = ssl_cert_store

configure_ssl_options(ssl_config)
configure_ciphers(ssl_config)
end

private

attr_reader :ssl

def configure_ssl_options(ssl_config)
ssl_config.add_trust_ca ssl[:ca_file] if ssl[:ca_file]
ssl_config.add_trust_ca ssl[:ca_path] if ssl[:ca_path]
ssl_config.client_cert = ssl[:client_cert] if ssl[:client_cert]
ssl_config.client_key = ssl[:client_key] if ssl[:client_key]
ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
end

def configure_ciphers(ssl_config)
if Gem::Version.new(Faraday::VERSION) >= Gem::Version.new('2.11.0') &&
ssl_config.respond_to?(:ciphers=)
ssl_config.ciphers = ssl[:ciphers]
end
end

# @param ssl [Hash]
# @return [OpenSSL::X509::Store]
def ssl_cert_store
return ssl[:cert_store] if ssl[:cert_store]

# Memoize the cert store so that the same one is passed to
# HTTPClient each time, to avoid resyncing SSL sessions when
# it's changed

# Use the default cert store by default, i.e. system ca certs
@ssl_cert_store ||= OpenSSL::X509::Store.new.tap(&:set_default_paths)
end

# @param ssl [Hash]
def ssl_verify_mode
ssl[:verify_mode] || begin
if ssl.fetch(:verify, true)
OpenSSL::SSL::VERIFY_PEER |
OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
else
OpenSSL::SSL::VERIFY_NONE
end
end
end
end
end
end