Class: Chef::Certificate

Inherits:
Object show all
Defined in:
lib/chef/certificate.rb

Class Method Summary collapse

Class Method Details

.gen_keypair(common_name, subject_alternative_name = nil) ⇒ Object

Creates a new key pair, and signs them with the signing certificate and key generated from generate_signing_ca above.

Parameters:

  • The (String)

    common name for the key pair.

  • The (Optional String)

    subject alternative name.

Returns:



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/chef/certificate.rb', line 85

def gen_keypair(common_name, subject_alternative_name = nil)

  Chef::Log.info("Creating new key pair for #{common_name}")

  # generate client keypair
  client_keypair = OpenSSL::PKey::RSA.generate(2048)

  client_cert = OpenSSL::X509::Certificate.new

  ca_cert = OpenSSL::X509::Certificate.new(File.read(Chef::Config[:signing_ca_cert]))

  info = [
    ["C", Chef::Config[:signing_ca_country]], 
    ["ST", Chef::Config[:signing_ca_state]], 
    ["L", Chef::Config[:signing_ca_location]], 
    ["O", Chef::Config[:signing_ca_org]],
    ["OU", "Certificate Service"], 
    ["CN", common_name ]
  ]

  client_cert.subject = OpenSSL::X509::Name.new(info)
  client_cert.issuer = ca_cert.subject
  client_cert.not_before = Time.now
  client_cert.not_after = Time.now + 10 * 365 * 24 * 60 * 60 # 10 years
  client_cert.public_key = client_keypair.public_key
  client_cert.serial = 1
  client_cert.version = 3

  ef = OpenSSL::X509::ExtensionFactory.new
  ef.subject_certificate = client_cert
  ef.issuer_certificate = ca_cert

  client_cert.extensions = [
          ef.create_extension("basicConstraints", "CA:FALSE", true),
          ef.create_extension("subjectKeyIdentifier", "hash")
  ]
  client_cert.add_extension ef.create_extension("subjectAltName", subject_alternative_name) if subject_alternative_name

  client_cert.sign(OpenSSL::PKey::RSA.new(File.read(Chef::Config[:signing_ca_key])), OpenSSL::Digest::SHA1.new)

  return client_cert.public_key, client_keypair
end

.gen_validation_key(name = , key_file = ) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/chef/certificate.rb', line 128

def gen_validation_key(name=Chef::Config[:validation_client_name], key_file=Chef::Config[:validation_key])
  # Create the validation key
  create_key = false 
  begin
    c = Chef::ApiClient.cdb_load(name)
  rescue Chef::Exceptions::CouchDBNotFound
    create_key = true
  end

  if create_key
    Chef::Log.info("Creating validation key...")
    api_client = Chef::ApiClient.new
    api_client.name(name)
    api_client.admin(true)
    api_client.create_keys
    api_client.cdb_save
    key_dir = File.dirname(key_file)
    FileUtils.mkdir_p(key_dir) unless File.directory?(key_dir)
    File.open(key_file, "w") do |f|
      f.print(api_client.private_key)
    end
  end
end

.generate_signing_caObject

Generates a new CA Certificate and Key, and writes them out to Chef::Config and Chef::Config.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/chef/certificate.rb', line 32

def generate_signing_ca
  ca_cert_file = Chef::Config[:signing_ca_cert]
  ca_keypair_file = Chef::Config[:signing_ca_key] 

  unless File.exists?(ca_cert_file) && File.exists?(ca_keypair_file)
    Chef::Log.info("Creating new signing certificate")
  
    [ ca_cert_file, ca_keypair_file ].each do |f|
      ca_basedir = File.dirname(f)
      FileUtils.mkdir_p ca_basedir
    end

    keypair = OpenSSL::PKey::RSA.generate(1024)

    ca_cert = OpenSSL::X509::Certificate.new
    ca_cert.version = 3
    ca_cert.serial = 1
    info = [
      ["C", Chef::Config[:signing_ca_country]], 
      ["ST", Chef::Config[:signing_ca_state]], 
      ["L", Chef::Config[:signing_ca_location]], 
      ["O", Chef::Config[:signing_ca_org]],
      ["OU", "Certificate Service"], 
      ["CN", "#{Chef::Config[:signing_ca_domain]}/emailAddress=#{Chef::Config[:signing_ca_email]}"]
    ]
    ca_cert.subject = ca_cert.issuer = OpenSSL::X509::Name.new(info)
    ca_cert.not_before = Time.now
    ca_cert.not_after = Time.now + 10 * 365 * 24 * 60 * 60 # 10 years
    ca_cert.public_key = keypair.public_key

    ef = OpenSSL::X509::ExtensionFactory.new
    ef.subject_certificate = ca_cert
    ef.issuer_certificate = ca_cert
    ca_cert.extensions = [
            ef.create_extension("basicConstraints", "CA:TRUE", true),
            ef.create_extension("subjectKeyIdentifier", "hash"),
            ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
    ]
    ca_cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
    ca_cert.sign keypair, OpenSSL::Digest::SHA1.new

    File.open(ca_cert_file, "w") { |f| f.write ca_cert.to_pem }
    File.open(ca_keypair_file, "w") { |f| f.write keypair.to_pem }
  end
  self
end