Class: Puppetserver::Ca::GenerateAction
- Inherits:
-
Object
- Object
- Puppetserver::Ca::GenerateAction
- Includes:
- Utils
- Defined in:
- lib/puppetserver/ca/generate_action.rb
Constant Summary collapse
- CA_EXTENSIONS =
[ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "keyCertSign, cRLSign", true], ["subjectKeyIdentifier", "hash", false], ["authorityKeyIdentifier", "keyid:always", false] ].freeze
- CERT_VALID_FROM =
Make the certificate valid as of yesterday, because so many people’s clocks are out of sync. This gives one more day of validity than people might expect, but is better than making every person who has a messed up clock fail, and better than having every cert we generate expire a day before the user expected it to when they asked for “one year”.
(Time.now - (60*60*24)).freeze
- SUMMARY =
"Generate a root and intermediate signing CA for Puppet Server"
- BANNER =
<<-BANNER Usage: puppetserver ca generate [--help] puppetserver ca generate [--config PATH] Description: Generate a root and intermediate signing CA for Puppet Server and store generated CA keys, certs, and crls on disk. To determine the target location, the default puppet.conf is consulted for custom values. If using a custom puppet.conf provide it with the --config flag Options: BANNER
Class Method Summary collapse
Instance Method Summary collapse
- #create_crl_for(ca_cert, ca_key, valid_until, signing_digest) ⇒ Object
- #extension_factory_for(ca, cert = nil) ⇒ Object
- #generate_root_and_intermediate_ca(settings, signing_digest) ⇒ Object
-
#initialize(logger) ⇒ GenerateAction
constructor
A new instance of GenerateAction.
- #parse(cli_args) ⇒ Object
- #parse_inputs(inputs) ⇒ Object
- #run(input) ⇒ Object
- #self_signed_ca(key, name, valid_until, signing_digest) ⇒ Object
- #sign_intermediate(ca_key, ca_cert, csr, valid_until, signing_digest) ⇒ Object
Constructor Details
#initialize(logger) ⇒ GenerateAction
Returns a new instance of GenerateAction.
43 44 45 |
# File 'lib/puppetserver/ca/generate_action.rb', line 43 def initialize(logger) @logger = logger end |
Class Method Details
.parser(parsed = {}) ⇒ Object
214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/puppetserver/ca/generate_action.rb', line 214 def self.parser(parsed = {}) OptionParser.new do |opts| opts. = BANNER opts.on('--help', 'Display this generate specific help output') do |help| parsed['help'] = true end opts.on('--config CONF', 'Path to puppet.conf') do |conf| parsed['config'] = conf end end end |
Instance Method Details
#create_crl_for(ca_cert, ca_key, valid_until, signing_digest) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/puppetserver/ca/generate_action.rb', line 134 def create_crl_for(ca_cert, ca_key, valid_until, signing_digest) crl = OpenSSL::X509::CRL.new crl.version = 1 crl.issuer = ca_cert.subject ef = extension_factory_for(ca_cert) crl.add_extension( ef.create_extension(["authorityKeyIdentifier", "keyid:always", false])) crl.add_extension( OpenSSL::X509::Extension.new("crlNumber", OpenSSL::ASN1::Integer(0))) crl.last_update = CERT_VALID_FROM crl.next_update = valid_until crl.sign(ca_key, signing_digest) crl end |
#extension_factory_for(ca, cert = nil) ⇒ Object
126 127 128 129 130 131 132 |
# File 'lib/puppetserver/ca/generate_action.rb', line 126 def extension_factory_for(ca, cert = nil) ef = OpenSSL::X509::ExtensionFactory.new ef.issuer_certificate = ca ef.subject_certificate = cert if cert ef end |
#generate_root_and_intermediate_ca(settings, signing_digest) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/puppetserver/ca/generate_action.rb', line 75 def generate_root_and_intermediate_ca(settings, signing_digest) valid_until = Time.now + settings[:ca_ttl] host = Puppetserver::Ca::Host.new(signing_digest) root_key = host.create_private_key(settings[:keylength]) root_cert = self_signed_ca(root_key, settings[:root_ca_name], valid_until, signing_digest) root_crl = create_crl_for(root_cert, root_key, valid_until, signing_digest) int_key = host.create_private_key(settings[:keylength]) int_csr = host.create_csr(settings[:ca_name], int_key) int_cert = sign_intermediate(root_key, root_cert, int_csr, valid_until, signing_digest) int_crl = create_crl_for(int_cert, int_key, valid_until, signing_digest) FileUtilities.ensure_dir(settings[:cadir]) file_properties = [ [settings[:cacert], [int_cert, root_cert]], [settings[:cakey], int_key], [settings[:rootkey], root_key], [settings[:cacrl], [int_crl, root_crl]] ] file_properties.each do |location, content| @logger.warn "#{location} exists, overwriting" if File.exist?(location) FileUtilities.write_file(location, content, 0640) end end |
#parse(cli_args) ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/puppetserver/ca/generate_action.rb', line 174 def parse(cli_args) parser, inputs, unparsed = parse_inputs(cli_args) if !unparsed.empty? @logger.err 'Error:' @logger.err 'Unknown arguments or flags:' unparsed.each do |arg| @logger.err " #{arg}" end @logger.err '' @logger.err parser.help exit_code = 1 else exit_code = nil end return inputs, exit_code end |
#parse_inputs(inputs) ⇒ Object
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/puppetserver/ca/generate_action.rb', line 195 def parse_inputs(inputs) parsed = {} unparsed = [] parser = self.class.parser(parsed) begin parser.order!(inputs) do |nonopt| unparsed << nonopt end rescue OptionParser::ParseError => e unparsed += e.args unparsed << inputs.shift unless inputs.first =~ /^-{1,2}/ retry end return parser, parsed, unparsed end |
#run(input) ⇒ Object
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 |
# File 'lib/puppetserver/ca/generate_action.rb', line 47 def run(input) # Validate config_path provided config_path = input['config'] if config_path errors = FileUtilities.validate_file_paths(config_path) return 1 if Utils.handle_errors(@logger, errors) end # Load, resolve, and validate puppet config settings puppet = PuppetConfig.parse(config_path) return 1 if Utils.handle_errors(@logger, puppet.errors) # Load most secure signing digest we can for cers/crl/csr signing. signer = SigningDigest.new return 1 if Utils.handle_errors(@logger, signer.errors) # Generate root and intermediate ca and put all the certificates, crls, # and keys where they should go. generate_root_and_intermediate_ca(puppet.settings, signer.digest) # Puppet's internal CA expects these file to exist. FileUtilities.ensure_file(puppet.settings[:serial], "001", 0640) FileUtilities.ensure_file(puppet.settings[:cert_inventory], "", 0640) @logger.inform "Generation succeeded. Find your files in #{puppet.settings[:cadir]}" return 0 end |
#self_signed_ca(key, name, valid_until, signing_digest) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/puppetserver/ca/generate_action.rb', line 103 def self_signed_ca(key, name, valid_until, signing_digest) cert = OpenSSL::X509::Certificate.new cert.public_key = key.public_key cert.subject = OpenSSL::X509::Name.new([["CN", name]]) cert.issuer = cert.subject cert.version = 2 cert.serial = 1 cert.not_before = CERT_VALID_FROM cert.not_after = valid_until ef = extension_factory_for(cert, cert) CA_EXTENSIONS.each do |ext| extension = ef.create_extension(*ext) cert.add_extension(extension) end cert.sign(key, signing_digest) cert end |
#sign_intermediate(ca_key, ca_cert, csr, valid_until, signing_digest) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/puppetserver/ca/generate_action.rb', line 152 def sign_intermediate(ca_key, ca_cert, csr, valid_until, signing_digest) cert = OpenSSL::X509::Certificate.new cert.public_key = csr.public_key cert.subject = csr.subject cert.issuer = ca_cert.subject cert.version = 2 cert.serial = 2 cert.not_before = CERT_VALID_FROM cert.not_after = valid_until ef = extension_factory_for(ca_cert, cert) CA_EXTENSIONS.each do |ext| extension = ef.create_extension(*ext) cert.add_extension(extension) end cert.sign(ca_key, signing_digest) cert end |