简体   繁体   English

连接到 S3 时出现“SSL_connect 返回=1 errno=0 状态=错误:证书验证失败”

[英]Getting “SSL_connect returned=1 errno=0 state=error: certificate verify failed” when connecting to S3

I have been trying to upload a photo to my AWS bucket, but running into the error mentioned in the title.我一直在尝试将照片上传到我的 AWS 存储桶,但遇到了标题中提到的错误。 I understand that it most likely has to do with my OpenSSL certificates, but any suggested solution that I have tried has failed thus far.我知道这很可能与我的 OpenSSL 证书有关,但到目前为止我尝试过的任何建议的解决方案都失败了。

I am running into this issue with ruby 2.3.1, Rails 4.1.8, aws-sdk-core 2.3.4, and carrierwave 0.11.0 on OSX Yosemite.我在 OSX Yosemite 上使用 ruby​​ 2.3.1、Rails 4.1.8、aws-sdk-core 2.3.4 和carrierwave 0.11.0 遇到了这个问题。

I have tried all available found at this similar issue as well, as others (this one being with Windows): https://github.com/aws/aws-sdk-core-ruby/issues/166#issuecomment-111603660我已经尝试了在这个类似问题上找到的所有可用内容,以及其他人(这个在 Windows 中): https : //github.com/aws/aws-sdk-core-ruby/issues/166#issuecomment-111603660

Here are some of my files:这是我的一些文件:

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头像_上传者.rb

class AvatarUploader < CarrierWave::Uploader::Base

  storage :aws

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
end

EDIT (more info):编辑(更多信息):

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'

Solutions tried:尝试的解决方案:

  • Aws.use_bundled_cert! aws.use_bundled_cert!
  • Download cert and reference manually手动下载证书和参考
  • I tried using Fog instead of carrierwave-aws我尝试使用 Fog 而不是carrierwave-aws
  • Tried reinstalling ruby after upgrading rbenv升级rbenv后尝试重新安装ruby

Here's the result of这是结果

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)

With the investigative help of @RodrigoM and your question update, it all started to make sense.在@RodrigoM 的调查帮助和您的问题更新下,这一切都开始变得有意义了。 There are actually two distinct problems that contribute to the error you observe:实际上有两个不同的问题会导致您观察到的错误:

  • Your openssl installation does not have the certificate chain needed to verify the Amazon server in its trusted certs store...您的 openssl 安装没有在其受信任的证书存储中验证 Amazon 服务器所需的证书链...
  • ...which is the exact situation that should be solved by adding Aws.use_bundled_cert! ...这是应该通过添加Aws.use_bundled_cert!解决的确切情况Aws.use_bundled_cert! to an initializer, according to the docs . 根据文档,到初始化程序。 But in this case it does not work because even though this command instructs the ruby openssl library to add various CA certs to the trusted store from the aws-sdk-core gem's CA bundle file , the file also does not contain the proper CA certificate as it is itself almost 2 years old and outdated .但在这种情况下它不起作用,因为即使此命令指示 ruby​​ openssl 库将各种 CA 证书从aws-sdk-core gem 的CA 捆绑文件添加到受信任的存储,该文件也不包含正确的 CA 证书,如它本身已经快 2 岁了,已经过时了 The intermediate CA cert CN=DigiCert Baltimore CA-2 G2 has been published Dec 8, 2015, so no wonder that the CA bundle file does not contain it.中间 CA 证书CN=DigiCert Baltimore CA-2 G2已于 2015 年 12 月 8 日发布,所以难怪 CA 捆绑文件不包含它。

Now, you have two options:现在,您有两个选择:

  • You can try to install this intermediate CA certificate, probably including the root CA cert ( CN=Baltimore CyberTrust Root ), to your openssl trusted certs store.您可以尝试将此中间 CA 证书(可能包括根 CA 证书( CN=Baltimore CyberTrust Root ))安装到您的 openssl 受信任证书存储中。 This should make the s_client command work.这应该使s_client命令工作。 But you might still run into issues using these trusted certs from ruby code.但是您可能仍然会遇到使用来自 ruby​​ 代码的这些可信证书的问题。 For concrete steps for making it work under ruby on OSX, refer to the Solution section of this SO question .有关使其在 OSX 上的 ruby​​ 下工作的具体步骤,请参阅此 SO 问题解决方案部分。

  • Also, since you are using a forked aws-sdk-ruby gem repository anyway, you may as well update the ca-bundle.crt file in your repo by adding the intermediate CA cert yourself (the root CA cert seems to be already present in the bundle).此外,由于您无论如何都在使用分叉的aws-sdk-ruby gem 存储库,您也可以通过自己添加中间 CA 证书来更新您的 repo 中ca-bundle.crt文件(根 CA 证书似乎已经存在于捆绑)。 For this you need to do the following:为此,您需要执行以下操作:

    • download the intermediate CA cert from the official page of the DigicertCA certificates (you can as well use the direct link above, but to obey security rules precisely you should also check the fingerprints)DigicertCA 证书的官方页面下载中间 CA 证书(您也可以使用上面的直接链接,但要严格遵守安全规则,您还应该检查指纹)
    • convert it to the PEM format (it gets downloaded in DER format) and add it to the cert bundle using the following openssl command:将其转换为 PEM 格式(以 DER 格式下载)并使用以下 openssl 命令将其添加到证书包中:

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

      after running this command, your ca-bundle.crt should contain the intermediate CA certificate at the end of the file.运行此命令后,您的ca-bundle.crt应在文件末尾包含中间 CA 证书。

    • Now simply push this updated bundle file to your repo and the Aws.use_bundled_cert!现在只需将此更新的捆绑文件推送到您的存储库和Aws.use_bundled_cert! should start working !应该开始工作了

    • If you care, perhaps the best would be also to start a github issue at the aws-sdk-ruby gem so that they update the cert bundle in their repo too...如果您关心,也许最好的方法是在aws-sdk-ruby gem 上启动 github 问题,以便他们也更新其存储库中的证书包...

Your Ruby code, AWS SDK etc are all good.你的 Ruby 代码、AWS SDK 等都很好。 This is not a Ruby or SDK issue.这不是 Ruby 或 SDK 问题。 The error message you initially describe, and your later post of the OpenSSL connect log both point to the root cause of the problem: A missing root certificate and/or improperly configured CA cert bundle in the OpenSSL framework.您最初描述的错误消息以及您稍后发布的 OpenSSL 连接日志都指向问题的根本原因:OpenSSL 框架中缺少根证书和/或未正确配置 CA 证书包。 A further clue is that the same code works on production.另一个线索是相同的代码适用于生产。 Its not the code.它不是代码。

The original error message itself points to OpenSSL certificate verification errors as you indicate.正如您所指出的,原始错误消息本身指向 OpenSSL 证书验证错误。 The stack traces also show Ruby internal lib errors in 2.3.1/lib/ruby/2.3.0/net/http.rb.堆栈跟踪还显示 2.3.1/lib/ruby/2.3.0/net/http.rb 中的 Ruby 内部库错误。 This is core network library that leverages the OpenSSL framework.这是利用 OpenSSL 框架的核心网络库。

The openssl s_client connect log more clearly shows the extact error number and message: 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

Until you get a Verify return code: 0 (ok) on the DigiCert Baltimore CA-2 CA with the openssl s-client test, your code will not work .在使用 openssl s-client 测试在 DigiCert Baltimore CA-2 CA 上获得Verify return code: 0 (ok) ,您的代码将无法工作

The DigiCert Baltimore CA-2 CA cert is not present or not properly referenced by your OpenSSL setup on that machine. DigiCert Baltimore CA-2 CA 证书不存在或该计算机上的 OpenSSL 设置未正确引用。 This is very common problem in broken or incomplete OpenSSL installations.这是损坏或不完整的 OpenSSL 安装中非常常见的问题。 You need to download that certificate, convert to PEM format, save it in a ca-certificate.crt file in your OpenSSL certs folder, then reference that file in your config, or in an environment variable SSL_CERT_FILE.您需要下载该证书,转换为 PEM 格式,将其保存在 OpenSSL 证书文件夹中的 ca-certificate.crt 文件中,然后在您的配置或环境变量 SSL_CERT_FILE 中引用该文件。

You can see a good solution for your root issue here您可以在此处查看解决根本问题的好方法

NOTE: To futher confirm this solution, you should run the openssl s_client test on your production server.注意:要进一步确认此解决方案,您应该在生产服务器上运行openssl s_client测试。 You should see it verifying the same CA without problem.您应该会看到它在验证相同的 CA 时没有问题。 Check the OpenSSL config and CA cert bundle configuration there to see why there is a difference between your production and development environment.检查那里的 OpenSSL 配置和 CA 证书捆绑配置,了解为什么您的生产和开发环境之间存在差异。

This issue may be due to invalid cert.此问题可能是由于证书无效。 when you call the URL(API)当您调用 URL(API) 时

You can first cross verify cert.您可以先交叉验证证书。 by typing command通过键入命令

openssl s_client -connect <url without https>:443

If you find any issue in the cert.如果您在证书中发现任何问题。 then updating cert.然后更新证书。 at certificate manager can fix this issue.证书管理器可以解决这个问题。

Try using these gems and this setup instead:尝试使用这些gems和此设置

Gemfile文件

gem "carrierwave", "~> 0.11.0"
gem 'carrierwave-aws', "~> 1.0.1"
gem "unf", "~> 0.1.4"

config/carrierwave.rb配置/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 *_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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 证书错误SSL_connect返回= 1 errno = 0状态=错误:证书验证失败 - certificate Error SSL_connect returned=1 errno=0 state=error: certificate verify failed SSL_connect 返回=1 errno=0 state=error: 证书验证失败(无法获取本地颁发者证书) - SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate) OpenSSL::SSL::SSLError: SSL_connect 返回=1 errno=0 state=error: 证书验证失败 - OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed Ruby rails 回形针 Seahorse::Client::NetworkingError(SSL_connect 返回=1 errno=0 状态=错误:证书验证失败) - Ruby rails paperclip Seahorse::Client::NetworkingError (SSL_connect returned=1 errno=0 state=error: certificate verify failed) Rails 5.1和Geocoder:SSL_connect返回= 1 errno = 0状态=错误:证书验证失败 - Rails 5.1 and Geocoder: SSL_connect returned=1 errno=0 state=error: certificate verify failed Faraday :: SSLError(SSL_connect返回= 1 errno = 0状态=错误:证书验证失败) - Faraday::SSLError (SSL_connect returned=1 errno=0 state=error: certificate verify failed) OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate) - OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate) Google Oauth SSL错误 - SSL_connect返回= 1 errno = 0状态= SSLv3读取服务器证书B:证书验证失败 - Google Oauth SSL error - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed SSL_connect 返回=1 errno=0 state=SSLv3 读取服务器证书B:证书验证失败 - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed SSL_connect返回= 1 errno = 0状态= SSLv3读取服务器证书B:Mac上的证书验证失败 - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed on Mac
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM