This class holds information about configuration elements which have changed, if the changed element is likely to affect the way the zone is audited. It keeps a list of the elements which we are interested in, the last value they were seen to have, and the timestamp at which that value changed (0 if they have not been seen to change). It allows the auditor to respond to changes in policy, and not raise errors when it sees records in the zone which still conform to the old policy. @TODO@ TEST CODE FOR THIS CLASS! @TODO@ TEST CODE FOR THE POLICY CHANGES FUNCTIONALITY - check that the auditor
does not produce errors as a result of changes in policy.
Initialised by the config parsing system - works out what has changed on startup, and stores the data internally. The only other public methods are inspection methods
# File ../../auditor/lib/kasp_auditor/changed_config.rb, line 93 def initialize(*args) zone = args[0] conf_file = args[1] kasp_file = args[2] config = args[3] working_folder = args[4] @syslog = args[5] return if args.length > 6 tracker_folder = (working_folder + File::SEPARATOR + "tracker").untaint begin Dir.mkdir(tracker_folder) unless File.directory?(tracker_folder) rescue Errno::ENOENT @syslog.log(LOG_ERR, "Can't create working folder : #{tracker_folder}") KASPAuditor.exit("Can't create working folder : #{tracker_folder}", 1) end tracker_filename = tracker_folder + File::SEPARATOR + zone + ".config" tracker_filename = (tracker_filename.to_s + "").untaint if !(load_last_config_changes(tracker_filename)) reset_elements(config, conf_file, kasp_file) end # Now get the timestamps for the conf and kasp files kasp_file = (kasp_file.to_s + "").untaint conf_file = (conf_file.to_s + "").untaint conf_timestamp = File.mtime(conf_file).to_i kasp_timestamp = File.mtime(kasp_file).to_i @conf_timestamp = conf_timestamp @kasp_timestamp = kasp_timestamp new_enforcer_interval = load_enforcer_interval(conf_file) # Has the enforcer interval changed? if !(new_enforcer_interval == @enforcer_interval.value) # If so, then store it along with the timestamp @enforcer_interval = Element.new(new_enforcer_interval, conf_timestamp) end # If the kasp_filename hasn't changed, then we can simply use the kasp_timestamp # for all KASP config items. timestamp = kasp_timestamp if (kasp_file != @kasp_filename.value) @kasp_filename = Element.new(kasp_file, conf_timestamp) if (conf_timestamp < timestamp) timestamp = conf_timestamp end end check_kasp_config(config, timestamp) write_config_changes(tracker_filename) end
# File ../../auditor/lib/kasp_auditor/changed_config.rb, line 244 def check_kasp_config(config, timestamp) # Check off the config items we're interested in from the KASP if (@rrsig_inception_offset.value != config.signatures.inception_offset) @rrsig_inception_offset = Element.new(config.signatures.inception_offset, timestamp) end if (@rrsig_refresh.value != config.signatures.refresh) @rrsig_refresh = Element.new(config.signatures.refresh, timestamp) end if (@rrsig_resign.value != config.signatures.resign) @rrsig_resign = Element.new(config.signatures.resign, timestamp) end if (@rrsig_jitter.value != config.signatures.jitter) @rrsig_jitter = Element.new(config.signatures.jitter, timestamp) end if (@rrsig_validity_default.value != config.signatures.validity.default) @rrsig_validity_default = Element.new(config.signatures.validity.default, timestamp) end if (@rrsig_validity_denial.value != config.signatures.validity.denial) @rrsig_validity_denial = Element.new(config.signatures.validity.denial, timestamp) end # NOW DO ZSKs AND KSKs check_key_config(@zsks, config.keys.zsks, timestamp) check_key_config(@ksks, config.keys.ksks, timestamp) end
# File ../../auditor/lib/kasp_auditor/changed_config.rb, line 269 def check_key_config(store_keys, config_keys, timestamp) # There is a ZSK lifetime for each ZSK element in the Keys config - [alg, alg_length, standby, lifetime] tuple # How do we identify each ZSK tuple? by algorithm/length - and hope that all aren't changed at once? # Or can we simply identify ones which *have not* changed? # i.e. go through, and if we don't recognise a ZSK or KSK, then set the timestamp to the new timestamp for that ZSK/KSK # and remember to remove ones we have seen in the past if we no longer see them now! used_config_keys = [] store_keys.each {|key| zsk_unchanged = false config_index = 0 config_keys.each {|config_zsk| zsk_unchanged = ((config_zsk.algorithm == key.value[0]) && (config_zsk.alg_length == key.value[1]) && (config_zsk.standby == key.value[2]) && (config_zsk.standby == key.value[3])) break if zsk_unchanged config_index += 1 } if (zsk_unchanged) # Mark the fact that we have used this config_zsk used_config_keys.push(config_index) else # This ZSK is no longer found. So - do we create a new ZSK, and delete the old one? store_keys.delete(key) end } # Now what about the config_zsk blocks which have not been used? index = 0 config_keys.each {|config_key| next if (used_config_keys.include?index) # This config_zsk was not used - create a new ZSK Element for it k = Key.new([config_key.algorithm, config_key.alg_length, config_key.standby, config_key.lifetime], timestamp) store_keys.push(k) index += 1 } end
# File ../../auditor/lib/kasp_auditor/changed_config.rb, line 308 def get_signature_timestamp # Get the earliest signature-related timestamp which is not 0 min_timestamp = 999999999999 [@rrsig_inception_offset, @rrsig_refresh, @rrsig_resign, @rrsig_jitter, @rrsig_validity_default, @rrsig_validity_denial].each {|el| if ((el.timestamp > 0) && (el.timestamp < min_timestamp)) min_timestamp = el.timestamp end } if (min_timestamp == 999999999999) return 0 else return min_timestamp end end
# File ../../auditor/lib/kasp_auditor/changed_config.rb, line 332 def load_enforcer_interval(conf_file) # Now load the enforcer_interval enforcer_interval = nil File.open((conf_file + "").untaint , 'r') {|file| doc = REXML::Document.new(file) begin e_i_text = doc.elements['Configuration/Enforcer/Interval'].text enforcer_interval = Config.xsd_duration_to_seconds(e_i_text) rescue Exception KASPAuditor.exit("Can't read Enforcer->Interval from Configuration", 1, @syslog) end } return enforcer_interval end
# File ../../auditor/lib/kasp_auditor/changed_config.rb, line 182 def load_last_config_changes(file) # Load the file storing the previously saved values for the config items # Return true if loaded successfully begin File.open(file) { |f| line = f.gets @kasp_filename = Element.new(line.split()[0].chop, line.split()[1].to_i) line = f.gets @enforcer_interval = Element.new(line.split()[0].to_i, line.split()[1].to_i) line = f.gets @rrsig_inception_offset = Element.new(line.split()[0].to_i, line.split()[1].to_i) line = f.gets @rrsig_refresh = Element.new(line.split()[0].to_i, line.split()[1].to_i) line = f.gets @rrsig_resign = Element.new(line.split()[0].to_i, line.split()[1].to_i) line = f.gets @rrsig_jitter = Element.new(line.split()[0].to_i, line.split()[1].to_i) line = f.gets @rrsig_validity_default = Element.new(line.split()[0].to_i, line.split()[1].to_i) line = f.gets @rrsig_validity_denial = Element.new(line.split()[0].to_i, line.split()[1].to_i) f.gets # "ZSK" @zsks = [] until ((line = f.gets) == "KSK\n") algorithm = line.split()[0] alg_length = line.split()[1].to_i standby = line.split()[2].to_i lifetime = line.split()[3].to_i zsk = Key.new([algorithm, alg_length, standby, lifetime], line.split()[4].to_i) @zsks.push(zsk) end @ksks = [] while (line = f.gets) algorithm = line.split()[0] alg_length = line.split()[1].to_i standby = line.split()[2].to_i lifetime = line.split()[3].to_i ksk = Key.new([algorithm, alg_length, standby, lifetime], line.split()[4].to_i) @ksks.push(ksk) end return true } rescue Exception return false end return false end
Reset the cache
# File ../../auditor/lib/kasp_auditor/changed_config.rb, line 231 def reset_elements(config, conf_file, kasp_file) @zsks = [] @ksks = [] @kasp_filename = Element.new(kasp_file) @enforcer_interval = Element.new(load_enforcer_interval(conf_file)) @rrsig_inception_offset = Element.new(config.signatures.inception_offset) @rrsig_refresh = Element.new(config.signatures.refresh) @rrsig_resign = Element.new(config.signatures.resign) @rrsig_jitter = Element.new(config.signatures.jitter) @rrsig_validity_default = Element.new(config.signatures.validity.default) @rrsig_validity_denial = Element.new(config.signatures.validity.denial) end
Has the Signature configuration for this policy changed?
# File ../../auditor/lib/kasp_auditor/changed_config.rb, line 325 def signature_config_changed? if (get_signature_timestamp != 0) return true end return false end
# File ../../auditor/lib/kasp_auditor/changed_config.rb, line 151 def write_config_changes(file) # Store the data to file! File.open(file + ".temp", 'w') { |f| f.puts(@kasp_filename.to_s) f.puts(@enforcer_interval.to_s) f.puts(@rrsig_inception_offset.to_s) f.puts(@rrsig_refresh.to_s) f.puts(@rrsig_resign.to_s) f.puts(@rrsig_jitter.to_s) f.puts(@rrsig_validity_default.to_s) f.puts(@rrsig_validity_denial.to_s) # ZSKs, KSKs f.puts("ZSK") @zsks.each {|zsk| f.puts(zsk.to_s) # algorithm, alg_length, standby, lifetime } f.puts("KSK") @ksks.each {|ksk| f.puts(ksk.to_s) } } # Now move the .temp file over the original begin File.delete(file) rescue Exception => e # print "Error deleting #{f} : #{e}\n" end File.rename(file+".temp", file) end
Generated with the Darkfish Rdoc Generator 2.