lib/autosign/validator.rb
# frozen_string_literal: true
require 'logging'
module Autosign
module Validator
# @return [Array] - A list of all the validator classes
# @param list [Array] - a list of validators to use, uses the settings list by default
# This returns a list of validators that were specified by the user and the exact
# order they want the validation to procede.
def self.validation_order(settings = Autosign::Config.new.settings, list = nil)
validation_order = list || settings['general']['validation_order']
# create a key pair where the key is the name of the validator and value is the class
validator_list = validator_classes.each_with_object({}) do |klass, acc|
acc[klass::NAME] = klass
acc
end
# filter out validators that do not exist
order = validation_order.map { |v| validator_list.fetch(v, nil) }.compact
@log = Logging.logger[self.class]
@log.debug("Validator order: #{order.inspect}")
order
end
# @summary
# Class method to attempt validation of a request against all validators which inherit from this class.
# The request is considered to be validated if any one validator succeeds.
# The first validator to pass shorts the validation process so other validators are not called.
# @param challenge_password [String] the challenge_password OID from the certificate signing request
# @param certname [String] the common name being requested in the certificate signing request
# @param raw_csr [String] the encoded X509 certificate signing request, as received by the autosign policy executable
# @return [Boolean] return true if the certificate should be signed, and false if it cannot be validated
def self.any_validator(challenge_password, certname, raw_csr, settings = Autosign::Config.new.settings)
@log = Logging.logger[self.class]
# find the first validator that passes and return the class
validator = validation_order(settings).find { |c| c.new(settings).validate(challenge_password, certname, raw_csr) }
if validator
@log.info "Successfully validated using #{validator::NAME}"
true
else
@log.info 'unable to validate using any validator'
false
end
end
private
# Find other classes that inherit from this class.
# Used to discover autosign validators. There is probably no reason to use
# this directly.
# @return [Array] of classes inheriting from Autosign::Validator
def self.validator_classes
validators = Dir.glob(File.join(__dir__, 'validator', '*')).sort.each {|k| require k }
ObjectSpace.each_object(Class).select { |klass| klass < Autosign::Validator::ValidatorBase }
end
end
end