我如何在 Ruby 中以编程方式检测证书问题
How can i detect certificate issue programmatically in Ruby
我遇到过一些客户在向我们的服务器 (HTTPS) 发帖时遇到错误。这是错误:
SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)
我可以使用此方法来检测证书链中的失败内容:
openssl s_client -connect <url>:443 -CAfile <path/cacert.pem>
但是,并不是所有的客户都愿意下载并安装openssl。所以,我想使用 ruby 代码添加此测试(我们已经在客户的计算机上安装了 ruby)。
这段 ruby 代码应该可以完成工作:
require 'openssl'
require 'socket'
CA_CERT = "<your-path-to-cert-file. e.g. cacert.pem>"
def verify_host(host)
puts "Connecting to: #{host} ..."
ctx = OpenSSL::SSL::SSLContext.new(:TLSv1_2)
ctx.ca_file = CA_CERT
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.verify_callback = lambda do | preverify_ok, cert_store |
cert = cert_store.current_cert
puts "subject: #{cert.subject}, issuer: #{cert.issuer}, valid: #{preverify_ok}"
preverify_ok
end
socket = TCPSocket.new host, 443
ssl_socket = OpenSSL::SSL::SSLSocket.new socket, ctx
ssl_socket.hostname = host
puts "SSL Version: #{ssl_socket.ssl_version}"
ssl_socket.connect
ssl_socket.sysclose
socket.close
rescue => ex
puts ex
end
示例用法:
verify_host('s3.amazonaws.com')
输出:
Connecting to: s3.amazonaws.com ...
SSL Version: TLSv1.3
subject: /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root, issuer: /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root, valid: true
subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2, issuer: /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root, valid: true
subject: /C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=s3.amazonaws.com, issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2, valid: true
我遇到过一些客户在向我们的服务器 (HTTPS) 发帖时遇到错误。这是错误:
SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)
我可以使用此方法来检测证书链中的失败内容:
openssl s_client -connect <url>:443 -CAfile <path/cacert.pem>
但是,并不是所有的客户都愿意下载并安装openssl。所以,我想使用 ruby 代码添加此测试(我们已经在客户的计算机上安装了 ruby)。
这段 ruby 代码应该可以完成工作:
require 'openssl'
require 'socket'
CA_CERT = "<your-path-to-cert-file. e.g. cacert.pem>"
def verify_host(host)
puts "Connecting to: #{host} ..."
ctx = OpenSSL::SSL::SSLContext.new(:TLSv1_2)
ctx.ca_file = CA_CERT
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.verify_callback = lambda do | preverify_ok, cert_store |
cert = cert_store.current_cert
puts "subject: #{cert.subject}, issuer: #{cert.issuer}, valid: #{preverify_ok}"
preverify_ok
end
socket = TCPSocket.new host, 443
ssl_socket = OpenSSL::SSL::SSLSocket.new socket, ctx
ssl_socket.hostname = host
puts "SSL Version: #{ssl_socket.ssl_version}"
ssl_socket.connect
ssl_socket.sysclose
socket.close
rescue => ex
puts ex
end
示例用法: verify_host('s3.amazonaws.com')
输出:
Connecting to: s3.amazonaws.com ...
SSL Version: TLSv1.3
subject: /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root, issuer: /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root, valid: true
subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2, issuer: /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root, valid: true
subject: /C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=s3.amazonaws.com, issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2, valid: true