class R509::Config::CAConfig
Stores a configuration for our CA.
Constants
- DEFAULT_CRL_START_SKEW_SECONDS
Default number of seconds to subtract from now when calculating the signing time of a
CRL
- DEFAULT_CRL_VALIDITY_HOURS
Default number of hours a
CRL
should be valid for- DEFAULT_OCSP_START_SKEW_SECONDS
Default number of seconds to subtract from now when calculating the signing time of an
OCSP
response- DEFAULT_OCSP_VALIDITY_HOURS
Default number of hours an
OCSP
response should be valid for
Attributes
Public Class Methods
Loads the named configuration config from a yaml string. @param [String] conf_name The name of the config within the file. Note
that a single yaml file can contain more than one configuration.
@param [String] yaml_data The filename to load yaml config data from.
# File lib/r509/config/ca_config.rb, line 271 def self.from_yaml(conf_name, yaml_data, opts = {}) conf = YAML.load(yaml_data) self.load_from_hash(conf[conf_name], opts) end
Load the configuration from a data hash. The same type that might be used when loading from a YAML file. @param [Hash] conf A hash containing all the configuration options @option opts [String] :ca_root_path The root path for the CA. Defaults to
the current working directory.
# File lib/r509/config/ca_config.rb, line 182 def self.load_from_hash(conf, opts = {}) if conf.nil? raise ArgumentError, "conf not found" end unless conf.is_a?(Hash) raise ArgumentError, "conf must be a Hash" end ca_root_path = Pathname.new(opts[:ca_root_path] || FileUtils.getwd) unless File.directory?(ca_root_path) raise R509Error, "ca_root_path is not a directory: #{ca_root_path}" end ca_cert = self.load_ca_cert(conf['ca_cert'], ca_root_path) ocsp_cert = self.load_ca_cert(conf['ocsp_cert'], ca_root_path) crl_cert = self.load_ca_cert(conf['crl_cert'], ca_root_path) ocsp_chain = build_ocsp_chain(conf['ocsp_chain'], ca_root_path) opts = { :ca_cert => ca_cert, :ocsp_cert => ocsp_cert, :crl_cert => crl_cert, :ocsp_chain => ocsp_chain, :crl_validity_hours => conf['crl_validity_hours'], :ocsp_validity_hours => conf['ocsp_validity_hours'], :ocsp_start_skew_seconds => conf['ocsp_start_skew_seconds'], :crl_md => conf['crl_md'] } if conf.key?("crl_list_file") opts[:crl_list_file] = (ca_root_path + conf['crl_list_file']).to_s end if conf.key?("crl_number_file") opts[:crl_number_file] = (ca_root_path + conf['crl_number_file']).to_s end opts[:profiles] = self.load_profiles(conf['profiles']) # Create the instance. self.new(opts) end
Used by load_from_hash
@param profiles [Hash] Hash of profiles @return [Hash] hash of parsed profiles
# File lib/r509/config/ca_config.rb, line 233 def self.load_profiles(profiles) profs = {} profiles.each do |profile, data| unless data["subject_item_policy"].nil? subject_item_policy = R509::Config::SubjectItemPolicy.new(data["subject_item_policy"]) end profs[profile] = R509::Config::CertProfile.new( :key_usage => data["key_usage"], :extended_key_usage => data["extended_key_usage"], :basic_constraints => data["basic_constraints"], :certificate_policies => data["certificate_policies"], :ocsp_no_check => data["ocsp_no_check"], :inhibit_any_policy => data["inhibit_any_policy"], :policy_constraints => data["policy_constraints"], :name_constraints => data["name_constraints"], :crl_distribution_points => data["crl_distribution_points"], :authority_info_access => data["authority_info_access"], :default_md => data["default_md"], :allowed_mds => data["allowed_mds"], :subject_item_policy => subject_item_policy ) end unless profiles.nil? profs end
Loads the named configuration config from a yaml file. @param [String] conf_name The name of the config within the file. Note
that a single yaml file can contain more than one configuration.
@param [String] yaml_file The filename to load yaml config data from.
# File lib/r509/config/ca_config.rb, line 262 def self.load_yaml(conf_name, yaml_file, opts = {}) conf = YAML.load_file(yaml_file) self.load_from_hash(conf[conf_name], opts) end
@option opts [R509::Cert] :ca_cert Cert+Key pair @option opts [Integer] :crl_validity_hours (168) The number of hours that
a CRL will be valid. Defaults to 7 days.
@option opts [Hash<String, R509::Config::CertProfile>] :profiles @option opts [String] :crl_number_file A file to save the CRL
number
into. This is only used if you use the default FileReaderWriter in CRL::Administrator
@option opts [String] :crl_md Optional digest for signing CRLs. sha1, sha224, sha256, sha384, sha512, md5. Defaults to R509::MessageDigest::DEFAULT_MD @option opts [String] :crl_list_file A file to serialize revoked certificates into. This
is only used if you use the default FileReaderWriter in CRL::Administrator
@option opts [R509::Cert] :ocsp_cert An optional cert+key pair
OCSP signing delegate
@option opts [R509::Cert] :crl_cert An optional cert+key pair
CRL signing delegate
@option opts [Array<OpenSSL::X509::Certificate>] :ocsp_chain An optional array
that constitutes the chain to attach to an OCSP response
@option opts [Integer] :ocsp_validity_hours Number of hours OCSP
responses should be valid for @option opts [Integer] :ocsp_start_skew_seconds The number of seconds to subtract from Time.now when calculating the signing time of an OCSP
response. This is important to handle bad user clocks. @option opts [Integer] :crl_validity_hours Number of hours CRLs should be valid for @option opts [Integer] :crl_start_skew_seconds The number of seconds to subtract from Time.now when calculating the signing time of a CRL
. This is important to handle bad user clocks.
# File lib/r509/config/ca_config.rb, line 99 def initialize(opts = {}) unless opts.key?(:ca_cert) raise ArgumentError, 'Config object requires that you pass :ca_cert' end @ca_cert = opts[:ca_cert] unless @ca_cert.is_a?(R509::Cert) raise ArgumentError, ':ca_cert must be of type R509::Cert' end parse_ocsp_data(opts) parse_crl_data(opts) @profiles = {} opts[:profiles].each_pair do |name, prof| set_profile(name, prof) end if opts[:profiles] end
Private Class Methods
# File lib/r509/config/ca_config.rb, line 396 def self.build_ocsp_chain(ocsp_chain_path, ca_root_path) ocsp_chain = [] unless ocsp_chain_path.nil? ocsp_chain_data = read_data(ca_root_path + ocsp_chain_path) cert_regex = /-----BEGIN CERTIFICATE-----.+?-----END CERTIFICATE-----/m ocsp_chain_data.scan(cert_regex) do |cert| ocsp_chain.push(OpenSSL::X509::Certificate.new(cert)) end end ocsp_chain end
# File lib/r509/config/ca_config.rb, line 312 def self.load_ca_cert(ca_cert_hash, ca_root_path) return nil if ca_cert_hash.nil? if ca_cert_hash.key?('engine') ca_cert = self.load_with_engine(ca_cert_hash, ca_root_path) end if ca_cert.nil? && ca_cert_hash.key?('pkcs12') ca_cert = self.load_with_pkcs12(ca_cert_hash, ca_root_path) end if ca_cert.nil? && ca_cert_hash.key?('cert') ca_cert = self.load_with_key(ca_cert_hash, ca_root_path) end ca_cert end
# File lib/r509/config/ca_config.rb, line 329 def self.load_with_engine(ca_cert_hash, ca_root_path) if ca_cert_hash.key?('key') raise ArgumentError, "You can't specify both key and engine" end if ca_cert_hash.key?('pkcs12') raise ArgumentError, "You can't specify both engine and pkcs12" end unless ca_cert_hash.key?('key_name') raise ArgumentError, "You must supply a key_name with an engine" end engine = R509::Engine.instance.load(ca_cert_hash['engine']) ca_key = R509::PrivateKey.new( :engine => engine, :key_name => ca_cert_hash['key_name'] ) ca_cert_file = ca_root_path + ca_cert_hash['cert'] ca_cert = R509::Cert.new( :cert => read_data(ca_cert_file), :key => ca_key ) ca_cert end
# File lib/r509/config/ca_config.rb, line 370 def self.load_with_key(ca_cert_hash, ca_root_path) ca_cert_file = ca_root_path + ca_cert_hash['cert'] if ca_cert_hash.key?('key') ca_key_file = ca_root_path + ca_cert_hash['key'] ca_key = R509::PrivateKey.new( :key => read_data(ca_key_file), :password => ca_cert_hash['password'] ) ca_cert = R509::Cert.new( :cert => read_data(ca_cert_file), :key => ca_key ) else # in certain cases (OCSP responders for example) we may want # to load a ca_cert with no private key ca_cert = R509::Cert.new(:cert => read_data(ca_cert_file)) end ca_cert end
# File lib/r509/config/ca_config.rb, line 354 def self.load_with_pkcs12(ca_cert_hash, ca_root_path) if ca_cert_hash.key?('cert') raise ArgumentError, "You can't specify both pkcs12 and cert" end if ca_cert_hash.key?('key') raise ArgumentError, "You can't specify both pkcs12 and key" end pkcs12_file = ca_root_path + ca_cert_hash['pkcs12'] ca_cert = R509::Cert.new( :pkcs12 => read_data(pkcs12_file), :password => ca_cert_hash['password'] ) ca_cert end
Public Instance Methods
@return [Integer] The number of profiles
# File lib/r509/config/ca_config.rb, line 148 def num_profiles @profiles.count end
@param [String] prof @return [R509::Config::CertProfile] The config profile.
# File lib/r509/config/ca_config.rb, line 140 def profile(prof) unless @profiles.key?(prof) raise R509::R509Error, "unknown profile '#{prof}'" end @profiles[prof] end
@param [String] name The name of the profile @param [R509::Config::CertProfile] prof The profile configuration
# File lib/r509/config/ca_config.rb, line 131 def set_profile(name, prof) unless prof.is_a?(R509::Config::CertProfile) raise TypeError, "profile is supposed to be a R509::Config::CertProfile" end @profiles[name] = prof end
@return [Hash]
# File lib/r509/config/ca_config.rb, line 153 def to_h hash = {} hash["ca_cert"] = build_cert_hash(@ca_cert) hash["ocsp_cert"] = build_cert_hash(@ocsp_cert) unless @ocsp_cert.nil? hash["crl_cert"] = build_cert_hash(@crl_cert) unless @crl_cert.nil? hash["ocsp_chain"] = "<add_path>" unless @ocsp_chain.nil? hash["ocsp_start_skew_seconds"] = @ocsp_start_skew_seconds hash["ocsp_validity_hours"] = @ocsp_validity_hours hash["crl_start_skew_seconds"] = @crl_start_skew_seconds hash["crl_validity_hours"] = @crl_validity_hours hash["crl_list_file"] = @crl_list_file unless @crl_list_file.nil? hash["crl_number_file"] = @crl_number_file unless @crl_number_file.nil? hash["crl_md"] = @crl_md hash["profiles"] = @profiles.merge(@profiles) { |_k, v| v.to_h } unless @profiles.empty? hash end
@return [YAML]
# File lib/r509/config/ca_config.rb, line 171 def to_yaml self.to_h.to_yaml end
Private Instance Methods
# File lib/r509/config/ca_config.rb, line 301 def build_cert_hash(obj) hash = { "cert" => "<add_path>" } if obj.key && obj.key.in_hardware? hash["engine"] = { :so_path => "<add_path>", :id => "<add_name>" } return hash elsif obj.key hash["key"] = "<add_path>" end hash end
# File lib/r509/config/ca_config.rb, line 391 def check_ocsp_crl_delegate(cert, kind) raise ArgumentError, ":#{kind}, if provided, must be of type R509::Cert" if cert && !cert.is_a?(R509::Cert) raise ArgumentError, ":#{kind} must contain a private key, not just a certificate" if cert && !cert.has_private_key? end
# File lib/r509/config/ca_config.rb, line 289 def parse_crl_data(opts) if opts.key?(:crl_cert) check_ocsp_crl_delegate(opts[:crl_cert], 'crl_cert') @crl_cert = opts[:crl_cert] end @crl_validity_hours = opts[:crl_validity_hours] || DEFAULT_CRL_VALIDITY_HOURS @crl_start_skew_seconds = opts[:crl_start_skew_seconds] || DEFAULT_CRL_START_SKEW_SECONDS @crl_number_file = opts[:crl_number_file] || nil @crl_list_file = opts[:crl_list_file] || nil @crl_md = opts[:crl_md] || R509::MessageDigest::DEFAULT_MD end
# File lib/r509/config/ca_config.rb, line 278 def parse_ocsp_data(opts) # ocsp data if opts.key?(:ocsp_cert) check_ocsp_crl_delegate(opts[:ocsp_cert], 'ocsp_cert') @ocsp_cert = opts[:ocsp_cert] end @ocsp_chain = opts[:ocsp_chain] if opts[:ocsp_chain].is_a?(Array) @ocsp_validity_hours = opts[:ocsp_validity_hours] || DEFAULT_OCSP_VALIDITY_HOURS @ocsp_start_skew_seconds = opts[:ocsp_start_skew_seconds] || DEFAULT_OCSP_START_SKEW_SECONDS end