簡體   English   中英

連接到 S3 時出現“SSL_connect 返回=1 errno=0 狀態=錯誤:證書驗證失敗”

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

我一直在嘗試將照片上傳到我的 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.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

頭像_上傳者.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
---

<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!解決的確切情況Aws.use_bundled_cert! 根據文檔,到初始化程序。 但在這種情況下它不起作用,因為即使此命令指示 ruby​​ openssl 庫將各種 CA 證書從aws-sdk-core gem 的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 問題解決方案部分。

  • 此外,由於您無論如何都在使用分叉的aws-sdk-ruby gem 存儲庫,您也可以通過自己添加中間 CA 證書來更新您的 repo 中ca-bundle.crt文件(根 CA 證書似乎已經存在於捆綁)。 為此,您需要執行以下操作:

    • DigicertCA 證書的官方頁面下載中間 CA 證書(您也可以使用上面的直接鏈接,但要嚴格遵守安全規則,您還應該檢查指紋)
    • 將其轉換為 PEM 格式(以 DER 格式下載)並使用以下 openssl 命令將其添加到證書包中:

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

      運行此命令后,您的ca-bundle.crt應在文件末尾包含中間 CA 證書。

    • 現在只需將此更新的捆綁文件推送到您的存儲庫和Aws.use_bundled_cert! 應該開始工作了

    • 如果您關心,也許最好的方法是在aws-sdk-ruby gem 上啟動 github 問題,以便他們也更新其存儲庫中的證書包...

你的 Ruby 代碼、AWS SDK 等都很好。 這不是 Ruby 或 SDK 問題。 您最初描述的錯誤消息以及您稍后發布的 OpenSSL 連接日志都指向問題的根本原因:OpenSSL 框架中缺少根證書和/或未正確配置 CA 證書包。 另一個線索是相同的代碼適用於生產。 它不是代碼。

正如您所指出的,原始錯誤消息本身指向 OpenSSL 證書驗證錯誤。 堆棧跟蹤還顯示 2.3.1/lib/ruby/2.3.0/net/http.rb 中的 Ruby 內部庫錯誤。 這是利用 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

在使用 openssl s-client 測試在 DigiCert Baltimore CA-2 CA 上獲得Verify return code: 0 (ok) ,您的代碼將無法工作

DigiCert Baltimore CA-2 CA 證書不存在或該計算機上的 OpenSSL 設置未正確引用。 這是損壞或不完整的 OpenSSL 安裝中非常常見的問題。 您需要下載該證書,轉換為 PEM 格式,將其保存在 OpenSSL 證書文件夾中的 ca-certificate.crt 文件中,然后在您的配置或環境變量 SSL_CERT_FILE 中引用該文件。

您可以在此處查看解決根本問題的好方法

注意:要進一步確認此解決方案,您應該在生產服務器上運行openssl s_client測試。 您應該會看到它在驗證相同的 CA 時沒有問題。 檢查那里的 OpenSSL 配置和 CA 證書捆綁配置,了解為什么您的生產和開發環境之間存在差異。

此問題可能是由於證書無效。 當您調用 URL(API) 時

您可以先交叉驗證證書。 通過鍵入命令

openssl s_client -connect <url without https>:443

如果您在證書中發現任何問題。 然后更新證書。 證書管理器可以解決這個問題。

嘗試使用這些gems和此設置

文件

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM