Skip to content

Instantly share code, notes, and snippets.

@shirkevich
Forked from sheerun/certgen.rb
Last active August 29, 2015 14:15
Show Gist options
  • Save shirkevich/363f849fd69bc97f6cae to your computer and use it in GitHub Desktop.
Save shirkevich/363f849fd69bc97f6cae to your computer and use it in GitHub Desktop.
# 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
["serv/#{$domain}/ca/key.pem", root.key_material.private_key],
["serv/#{$domain}/ca/cert.pem", root.to_pem],
# Those are default filenames expected by Docker
["serv/#{$domain}/ca.pem", root.to_pem],
["serv/#{$domain}/key.pem", client.key_material.private_key],
["serv/#{$domain}/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}"
source "https://rubygems.org"
gem "certificate_authority"
GEM
remote: https://rubygems.org/
specs:
activemodel (4.2.0)
activesupport (= 4.2.0)
builder (~> 3.1)
activesupport (4.2.0)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
builder (3.2.2)
certificate_authority (0.1.6)
activemodel (>= 3.0.6)
i18n (0.7.0)
json (1.8.2)
minitest (5.5.1)
thread_safe (0.3.4)
tzinfo (1.2.2)
thread_safe (~> 0.1)
PLATFORMS
ruby
DEPENDENCIES
certificate_authority
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment