连接到S3时,获取“SSL_connect返回= 1 errno = 0状态=错误:证书validation失败”

我一直试图将照片上传到我的AWS桶,但遇到了标题中提到的错误。 我知道它很可能与我的OpenSSL证书有关,但是我尝试过的任何建议的解决方案到目前为止都失败了。

我在OSX Yosemite上遇到了ruby 2.3.1,Rails 4.1.8,aws-sdk-core 2.3.4和carrierwave 0.11.0这个问题。

我已经尝试了在这个类似问题上找到的所有可用内容,以及其他(这一个在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 

编辑(更多信息):

 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
  • 尝试升级rbenv后重新安装ruby

这是结果

 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 ---  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-ctx: Master-Key:  Key-Arg : None Start Time: 1463697130 Timeout : 300 (sec) Verify return code: 0 (ok) 

随着@RodrigoM的调查帮助和你的问题更新,这一切都开始有意义了。 实际上有两个不同的问题会导致您观察到的错误:

  • 您的openssl安装没有validation其受信任证书存储中的Amazon服务器所需的证书链…
  • …这是应该通过添加Aws.use_bundled_cert!来解决的确切情况Aws.use_bundled_cert! 根据文档 ,初始化程序。 但在这种情况下,它不起作用,因为即使此命令指示ruby openssl库从aws-sdk-core gem的CA捆绑文件向受信任存储添加各种CA证书, 该文件也不包含正确的CA证书,因为它本身已近2年,已经过时了 。 中间CA证书CN=DigiCert Baltimore CA-2 G2已于2015年12月8日发布,因此难怪CA捆绑文件不包含它。

现在,您有两种选择:

  • 您可以尝试将此中间CA证书(可能包括根CA证书( CN=Baltimore CyberTrust Root ))安装到您的openssl受信任证书商店。 这应该使s_client命令工作。 但是,您可能仍会遇到使用ruby代码中的这些受信任证书的问题。 有关在OSX上使其在ruby下工作的具体步骤,请参阅此SO问题的“ 解决方案”部分。

  • 此外,既然你正在使用fork的aws-sdk-ruby gem存储库,你也可以通过自己添加中间CA证书来更新repo中的ca-bundle.crt文件 (根CA证书似乎已经存在于捆绑)。 为此,您需要执行以下操作:

    • 从DigicertCA证书的官方页面下载中间CA证书(您也可以使用上面的直接链接,但要严格遵守安全规则,您还应检查指纹)
    • 将其转换为PEM格式(以DER格式下载)并使用以下openssl命令将其添加到cert包中:

       openssl x509 -in DigiCertBaltimoreCA-2G2.crt -inform DER >> ca-bundle.crt 

      运行此命令后,您的ca-bundle.crt应包含文件末尾的中间CA证书。

    • 现在只需将此更新的捆绑文件推送到您的Aws.use_bundled_cert!Aws.use_bundled_cert! 应该开始工作了

    • 如果你关心,也许最好也是在aws-sdk-ruby gem上启动一个github问题,这样他们也可以在他们的repo中更新cert bundle …

您的Ruby代码,AWS SDK等都很好。 这不是Ruby或SDK问题。 您最初描述的错误消息以及您之后发布的OpenSSL连接日志都指出了问题的根本原因:OpenSSL框架中缺少根证书和/或未正确配置的CA证书捆绑包。 进一步的线索是相同的代码适用于生产。 它不是代码。

原始错误消息本身指向您指示的OpenSSL证书validation错误。 堆栈跟踪还显示2.3.1 / lib / ruby​​ / 2.3.0 / net / http.rb中的Ruby内部lib错误。 这是利用OpenSSL框架的核心网络库。

openssl s_client连接日志更清楚地显示了extact错误号和消息:

 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 

在使用openssl s-client测试在DigiCert Baltimore CA-2 CA上获得Verify return code: 0 (ok) ,您的代码将无效

此计算机上的OpenSSL设置不存在或未正确引用DigiCert Baltimore CA-2 CA证书。 这是破碎或不完整的OpenSSL安装中非常常见的问题。 您需要下载该证书,转换为PEM格式,将其保存在OpenSSL certs文件夹中的ca-certificate.crt文件中,然后在您的配置或环境变量SSL_CERT_FILE中引用该文件。

您可以在此处查看针对根问题的良好解决方案

注意:要进一步确认此解决方案,您应该在生产服务器上运行openssl s_client测试。 您应该看到它在没有问题的情况下validation相同的CA. 检查那里的OpenSSL配置和CA证书捆绑包配置,了解为什么生产和开发环境之间存在差异。

请尝试使用这些gem和此设置

的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's temp folder for uploads def cache_dir "#{Rails.root}/tmp/uploads" end