Вопрос:
Я пытаюсь загрузить фотографию в свой ковш AWS, но столкнулся с ошибкой, упомянутой в заголовке. Я понимаю, что это скорее всего связано с моими сертификатами OpenSSL, но любое предлагаемое решение, которое я пробовал, до сих пор не удалось.
Я столкнулся с этой проблемой с ruby 2.3.1, Rails 4.1.8, aws-sdk-core 2.3.4 и несущей-несущей 0.11.0 на OSX Yosemite.
Я тоже пробовал все доступные в этой аналогичной проблеме, как и другие (это один из Windows): https://github.com/aws/aws-sdk-core-ruby/issues/166#issuecomment-111603660
Вот некоторые из моих файлов:
carrierwave.rb
CarrierWave.configure do |config| # required config.aws_credentials = { access_key_id: Rails.application.secrets.aws_access_key_id, # required secret_access_key: Rails.application.secrets.aws_access_key, # required region: ‘eu-west-2’ # optional, defaults to ‘us-east-1’ } config.aws_bucket = Rails.application.secrets.aws_bucket # required config.fog_attributes = { ‘Cache-Control’ => «max-age=#{365.day.to_i}» } # optional, defaults to {} end
avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base storage :aws def store_dir «uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}» end end
EDIT (подробнее):
stack trace: Seahorse::Client::NetworkingError — SSL_connect returned=1 errno=0 state=error: certificate verify failed: /Users/stevenharlow/.rbenv/versions/2.3.1/lib/ruby/2.3.0/net/http.rb:933:in `connect_nonblock’ /Users/stevenharlow/.rbenv/versions/2.3.1/lib/ruby/2.3.0/net/http.rb:933:in `connect’ /Users/stevenharlow/.rbenv/versions/2.3.1/lib/ruby/2.3.0/net/http.rb:863:in `do_start’ /Users/stevenharlow/.rbenv/versions/2.3.1/lib/ruby/2.3.0/net/http.rb:858:in `start’ /Users/stevenharlow/.rbenv/versions/2.3.1/lib/ruby/2.3.0/delegate.rb:83:in `method_missing’ aws-sdk-core (2.3.4) lib/seahorse/client/net_http/connection_pool.rb:292:in `start_session’ aws-sdk-core (2.3.4) lib/seahorse/client/net_http/connection_pool.rb:104:in `session_for’ aws-sdk-core (2.3.4) lib/seahorse/client/net_http/handler.rb:109:in `session’
Решения попытались:
- Aws.use_bundled_cert!
- Загрузите сертификат и ссылку вручную
- Я пытался использовать Fog вместо carrierwave-aws
- Попробовал переустановить ruby после обновления rbenv
Здесь результат
CONNECTED(00000003) depth=1 /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2 verify error:num=20:unable to get local issuer certificate verify return:0 — Certificate chain 0 s:/C=US/ST=Washington/L=Seattle/O=Amazon.com Inc./CN=*.s3-us-west-2.amazonaws.com i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2 i:/C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root — <certificate info> No client certificate CA names sent — SSL handshake has read 2703 bytes and written 456 bytes — New, TLSv1/SSLv3, Cipher is AES128-SHA Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1 Cipher : AES128-SHA Session-ID: <session-id> Session-ID-ctx: Master-Key: <master-key> Key-Arg : None Start Time: 1463697130 Timeout : 300 (sec) Verify return code: 0 (ok) Лучший ответ:
С помощью следственной помощи @RodrigoM и вашего обновления вопроса все стало иметь смысл. На самом деле существуют две разные проблемы, которые способствуют обнаружению ошибки:
- У вашей установки openssl нет цепочки сертификатов, необходимой для проверки сервера Amazon в его доверенном хранилище сертификатов…
- … это точная ситуация, которая должна быть решена путем добавления Aws.use_bundled_cert! к инициализатору в соответствии с документами. Но в этом случае это не сработает, потому что хотя эта команда указывает библиотеке ruby openssl добавлять различные сертификаты CA в доверенное хранилище из aws-sdk-core gem CA пакетный файл, файл также не содержит надлежащего сертификата ЦС, поскольку он сам почти 2 года и устарел. Промежуточный сертификат CA CN=DigiCert Baltimore CA-2 G2 был опубликован 8 декабря 2015 г., поэтому неудивительно, что файл пакета CA не содержит его.
Теперь у вас есть два варианта:
-
Вы можете попробовать установить этот промежуточный сертификат CA, возможно, включая корневой сертификат CA (CN=Baltimore CyberTrust Root), к вашему openssl trusted certs store. Это должно сделать команду s_client. Но вы все равно можете столкнуться с проблемами, используя эти доверенные сертификаты из ruby-кода. Для конкретных шагов, чтобы заставить его работать под рубином на OSX, обратитесь к разделу Решение этого вопроса SO.
-
Кроме того, поскольку вы все равно используете разветвленный репозиторий aws-sdk-ruby gem, вы также можете обновить файл ca-bundle.crt в вашем репо, добавив сертификат промежуточного CA (корневой сертификат CA уже присутствует в комплекте). Для этого вам необходимо сделать следующее:
- загрузите промежуточный сертификат CA с официальной страницы сертификатов DigicertCA (вы также можете использовать прямую ссылку выше, но подчиняться правила безопасности точно вы также должны проверить отпечатки пальцев)
-
преобразуйте его в формат PEM (он загружается в формате DER) и добавьте его в пакет сертификатов, используя следующую команду openssl:
openssl x509 -in DigiCertBaltimoreCA-2G2.crt -inform DER >> ca-bundle.crt
после выполнения этой команды, ваш ca-bundle.crt должен содержать промежуточный сертификат CA в конце файла.
-
Теперь просто переместите этот обновленный файл пакета в ваше репо и Aws.use_bundled_cert! должен начать работать!
- Если вам небезразлично, возможно, лучшим было бы также запустить проблему github в камне aws-sdk-ruby, чтобы они также обновили комплект сертификатов в своем репо…
Ответ №1
Ваш Ruby-код, AWS SDK и т.д. все в порядке. Это не проблема с Ruby или SDK. Сообщение об ошибке, которое вы изначально описываете, а ваша более поздняя публикация журнала подключения OpenSSL указывает на основную причину проблемы: Отсутствует корневой сертификат и/или неправильно настроенный пакет CA cert в среде OpenSSL. Еще одна подсказка заключается в том, что тот же код работает на производстве. Это не код.
Само исходное сообщение об ошибке указывает на ошибки проверки сертификата OpenSSL, как вы указываете. Трассировка стека также показывает внутренние ошибки Ruby в версии 2.3.1/lib/ruby /2.3.0/net/http.rb. Это основная сетевая библиотека, которая использует структуру OpenSSL.
Журнал подключения openssl s_client более четко показывает номер и сообщение об ошибке:
depth=1 /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2 verify error:num=20:unable to get local issuer certificate
Пока вы не получите Verify return code: 0 (ok) в CA DigiCert Baltimore CA-2 с тестом s-client openssl, ваш код не будет работать.
Сертификат CA DigiCert Baltimore CA-2 CA отсутствует или неправильно указан в настройках OpenSSL на этом компьютере. Это очень распространенная проблема в сломанной или неполной установке OpenSSL. Вам необходимо загрузить этот сертификат, конвертировать в формат PEM, сохранить его в файле ca-certificate.crt в своей папке certs.exe, а затем ссылаться на этот файл в вашей конфигурации или на переменную среды SSL_CERT_FILE.
Вы можете увидеть хорошее решение для вашей корневой проблемы здесь
ПРИМЕЧАНИЕ. Чтобы подтвердить это решение, вы должны запустить тест openssl s_client на вашем производственном сервере. Вы должны увидеть, что он проверяет тот же СА без проблем. Проверьте конфигурацию конфигурационного файла OpenSSL и CA cert, чтобы понять, почему существует разница между вашей производственной средой и средой разработки.
Ответ №2
Попробуйте использовать эти драгоценные камни и эту настройку:
Gemfile
gem «carrierwave», «~> 0.11.0» gem ‘carrierwave-aws’, «~> 1.0.1» gem «unf», «~> 0.1.4»
конфигурации /carrierwave.rb
require ‘carrierwave’ require ‘carrierwave/orm/activerecord’ CarrierWave.configure do |config| config.storage = :aws # required config.aws_bucket = Rails.application.secrets.aws_bucket # required config.aws_acl = :public_read config.aws_credentials = { access_key_id: Rails.application.secrets.aws_access_key_id, # required secret_access_key: Rails.application.secrets.aws_access_key # required } config.aws_attributes = { cache_control: ‘max-age=31536000’, expires: 1.year.from_now.httpdate } end
* _ uploader.rb
storage :aws def store_dir «uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}» end # Use Heroku temp folder for uploads def cache_dir «#{Rails.root}/tmp/uploads» end