[英]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:尝试的解决方案:
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:
实际上有两个不同的问题会导致您观察到的错误:
Aws.use_bundled_cert!
Aws.use_bundled_cert!
解决的确切情况Aws.use_bundled_cert!
to an initializer, according to the docs . 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 .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.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:为此,您需要执行以下操作:
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 !应该开始工作了!
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.