Last active
April 10, 2022 15:39
-
-
Save sheerun/ccdeff92ea1668f3c75f to your computer and use it in GitHub Desktop.
Docker TLS certificate generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Generates necessary certificates to ~/.docker | |
# | |
# Usage: | |
# bundle install | |
# ruby certgen.rb <domain> | |
require 'certificate_authority' | |
require 'fileutils' | |
if ARGV.empty? | |
puts "Usage: ruby certgen.rb <domain>" | |
exit 1 | |
end | |
$domain = ARGV[0] | |
$certs_path = File.join(ENV['HOME'], '.docker') | |
def certificate_authority | |
cert_path = File.join($certs_path, 'ca', 'cert.pem') | |
ca_path = File.join($certs_path, 'ca', 'key.pem') | |
key_material = if File.exist?(ca_path) | |
key = OpenSSL::PKey::RSA.new(File.read(ca_path)) | |
mem_key = CertificateAuthority::MemoryKeyMaterial.new | |
mem_key.public_key = key.public_key | |
mem_key.private_key = key | |
mem_key | |
else | |
mem_key = CertificateAuthority::MemoryKeyMaterial.new | |
mem_key.generate_key | |
mem_key | |
end | |
if File.exist?(cert_path) | |
raw_cert = File.read(cert_path) | |
openssl = OpenSSL::X509::Certificate.new(raw_cert) | |
cert = CertificateAuthority::Certificate.from_openssl(openssl) | |
cert.key_material = key_material | |
cert | |
else | |
root = CertificateAuthority::Certificate.new | |
root.subject.common_name = $domain | |
root.serial_number.number = 1 | |
root.signing_entity = true | |
root.key_material = key_material | |
ca_profile = { | |
"extensions" => { | |
"keyUsage" => { | |
"usage" => [ "critical", "keyCertSign" ] | |
} | |
} | |
} | |
root.sign!(ca_profile) | |
root | |
end | |
end | |
def server_certificate(root) | |
server = CertificateAuthority::Certificate.new | |
server.subject.common_name = $domain | |
server.serial_number.number = rand(3..100000) | |
server.parent = root | |
server.key_material.generate_key | |
server.sign! | |
server | |
end | |
def client_certificate(root) | |
client = CertificateAuthority::Certificate.new | |
client.subject.common_name = $domain | |
client.serial_number.number = 2 | |
client.parent = root | |
client.key_material.generate_key | |
signing_profile = { | |
"extensions" => { | |
"extendedKeyUsage" => { | |
"usage" => [ "clientAuth" ] | |
} | |
} | |
} | |
client.sign!(signing_profile) | |
client | |
end | |
root = certificate_authority | |
server = server_certificate(root) | |
client = client_certificate(root) | |
[ | |
# You can reuse this file to generate more certs | |
['ca/key.pem', root.key_material.private_key], | |
['ca/cert.pem', root.to_pem], | |
# Those are default filenames expected by Docker | |
['ca.pem', root.to_pem], | |
['key.pem', client.key_material.private_key], | |
['cert.pem', client.to_pem], | |
# Those files are supposed to be uploaded to server | |
["#{$domain}/ca.pem", root.to_pem], | |
["#{$domain}/key.pem", server.key_material.private_key], | |
["#{$domain}/cert.pem", server.to_pem] | |
].each do |name, contents| | |
path = File.join($certs_path, name) | |
FileUtils.mkdir_p(File.dirname(path)) | |
File.write(path, contents) | |
File.chmod(0600, path) | |
end | |
puts "CA certificates are in #{$certs_path}/ca" | |
puts "Client certificates are in #{$certs_path}" | |
puts "Server certificates are in #{$certs_path}/#{$domain}" |
请教一下, 在客户端连接的时候, 要如何设置才能使用双向TLS验证呢?
require 'net/https'
require 'uri'
require 'openssl'
uri = URI.parse('https://test.com:2375/containers/json')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.cert = OpenSSL::X509::Certificate.new(File.read("/Users/cbd/.docker/cert.pem"))
http.key = OpenSSL::PKey::RSA.new((File.read("/Users/cbd/.docker/key.pem")))
http.ca_file = "/Users/cbd/.docker/"
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.start {
http.request_get(uri.path) { |res|
print res.body
}
}
用 VERIFY_NONE 是可以连通的, 也就是服务器验证客户端证书成功了. 但使用 VERIFY_PEER 的时候就报错.
是哪个环节出问题了呢?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
its missing the subjectAltName which makes docker-compose complaint about urllib3
at server_certificate add this
and have $ip point to the ip of your server
signing_profile = {
"extensions" => {
"subjectAltName" => {"uris" => ["https://#{$domain}:2376"], "https://#{$ip}:2376"],
"ips" => ["#{$ip}","127.0.0.1"]
}
}
}