Module: Porkadot::Assets::CertsUtils

Instance Method Summary collapse

Instance Method Details

#_ca_cert(path, name, root_key) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/porkadot/assets/certs.rb', line 108

def _ca_cert(path, name, root_key)
  root_ca = unsigned_cert(name, root_key, nil, 2 * 365 * 24 * 60 * 60)

  ef = OpenSSL::X509::ExtensionFactory.new
  ef.subject_certificate = root_ca
  ef.issuer_certificate = root_ca
  root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
  root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
  root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
  root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
  root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)

  File.open path, 'wb' do |f|
    f.write root_ca.to_pem
  end

  return root_ca
end

#_client_cert(path, name, client_key, ca_cert, ca_key) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/porkadot/assets/certs.rb', line 127

def _client_cert(path, name, client_key, ca_cert, ca_key)
  cert = unsigned_cert(name, client_key, ca_cert, 1 * 365 * 24 * 60 * 60)

  ef = OpenSSL::X509::ExtensionFactory.new
  ef.subject_certificate = cert
  ef.issuer_certificate = ca_cert
  cert.add_extension(ef.create_extension("basicConstraints","CA:FALSE",true))
  cert.add_extension(ef.create_extension("keyUsage","nonRepudiation, digitalSignature, keyEncipherment", true))
  cert.add_extension(ef.create_extension("extendedKeyUsage","clientAuth",true))
  cert.sign(ca_key, OpenSSL::Digest::SHA256.new)

  File.open path, 'wb' do |f|
    f.write cert.to_pem
  end

  return cert
end

#ca_cert(refresh = false) ⇒ Object



27
28
29
30
31
32
33
34
35
36
# File 'lib/porkadot/assets/certs.rb', line 27

def ca_cert(refresh=false)
  return @ca_cert if defined?(@ca_cert)
  if File.file?(config.ca_cert_path) and !refresh
    self.logger.debug("--> CA cert already exists, skipping: #{config.ca_cert_path}")
    @ca_cert = OpenSSL::X509::Certificate.new(File.read(config.ca_cert_path))
  else
    @ca_cert = _ca_cert(config.ca_cert_path, self.ca_name, self.ca_key)
  end
  return @ca_cert
end

#ca_keyObject



22
23
24
25
# File 'lib/porkadot/assets/certs.rb', line 22

def ca_key
  @ca_key ||= private_key(config.ca_key_path)
  return @ca_key
end

#ca_nameObject



18
19
20
# File 'lib/porkadot/assets/certs.rb', line 18

def ca_name
  raise "Not implemented"
end

#client_cert(refresh = false) ⇒ Object



47
48
49
50
51
52
53
54
55
56
# File 'lib/porkadot/assets/certs.rb', line 47

def client_cert(refresh=false)
  return @client_cert if defined?(@client_cert)
  if File.file?(config.client_cert_path) and !refresh
    self.logger.debug("--> Client cert already exists, skipping: #{config.client_cert_path}")
    @client_cert = OpenSSL::X509::Certificate.new(File.read(config.client_cert_path))
  else
    @client_cert = _client_cert(config.client_cert_path, self.client_name, self.client_key, self.ca_cert(false), self.ca_key)
  end
  return @client_cert
end

#client_keyObject



42
43
44
45
# File 'lib/porkadot/assets/certs.rb', line 42

def client_key
  @client_key ||= private_key(config.client_key_path)
  return @client_key
end

#client_nameObject



38
39
40
# File 'lib/porkadot/assets/certs.rb', line 38

def client_name
  raise "Not implemented"
end

#private_key(path) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/porkadot/assets/certs.rb', line 58

def private_key(path)
  if File.file?(path)
    self.logger.debug("--> Private key already exists, skipping: #{path}")
    key = OpenSSL::PKey::RSA.new File.read(path)
  else
    dir = File.dirname(path)
    FileUtils.mkdir_p(dir)
    key = OpenSSL::PKey::RSA.new 2048
    File.open path, 'wb' do |f|
      f.write key.export(nil, nil)
    end
  end
  return key
end

#public_key(path, key) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/porkadot/assets/certs.rb', line 73

def public_key(path, key)
  public_key = key.public_key
  if File.file?(path)
    self.logger.debug("--> Public key already exists, skipping: #{path}")
  else
    dir = File.dirname(path)
    FileUtils.mkdir_p(dir)
    File.open path, 'wb' do |f|
      f.write public_key.export(nil, nil)
    end
  end
  return public_key
end

#random_numberObject



87
88
89
# File 'lib/porkadot/assets/certs.rb', line 87

def random_number
  return (0...8).map{ (0 + rand(10)) }.join.to_i
end

#to_base64(key_or_cert) ⇒ Object



14
15
16
# File 'lib/porkadot/assets/certs.rb', line 14

def to_base64(key_or_cert)
  Base64.strict_encode64(self.to_pem(key_or_cert))
end

#to_pem(key_or_cert) ⇒ Object



10
11
12
# File 'lib/porkadot/assets/certs.rb', line 10

def to_pem(key_or_cert)
  self.send(key_or_cert.to_sym).to_pem
end

#unsigned_cert(name, key, ca_cert = nil, expire = (1 * 365 * 24 * 60 * 60)) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/porkadot/assets/certs.rb', line 91

def unsigned_cert(name, key, ca_cert=nil, expire=(1 * 365 * 24 * 60 * 60))
  cert = OpenSSL::X509::Certificate.new

  cert.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
  cert.serial = self.random_number
  cert.subject = OpenSSL::X509::Name.parse name
  if ca_cert
    cert.issuer = ca_cert.subject
  else
    cert.issuer = cert.subject # root CA's are "self-signed"
  end
  cert.public_key = key.public_key
  cert.not_before = Time.now
  cert.not_after = cert.not_before + expire
  return cert
end