diff --git a/lib/cryptcheck.rb b/lib/cryptcheck.rb index 7865999..5903ce2 100644 --- a/lib/cryptcheck.rb +++ b/lib/cryptcheck.rb @@ -30,8 +30,7 @@ module CryptCheck end end - autoload :Status, 'cryptcheck/status' - autoload :Statused, 'cryptcheck/statused' + autoload :State, 'cryptcheck/state' autoload :Logger, 'cryptcheck/logger' autoload :Tls, 'cryptcheck/tls' module Tls @@ -96,7 +95,7 @@ module CryptCheck else server.new *a, **kargs end - ap s.status + ap s.states exit if grade g = grade.new s diff --git a/lib/cryptcheck/status.rb b/lib/cryptcheck/status.rb deleted file mode 100644 index 464ee55..0000000 --- a/lib/cryptcheck/status.rb +++ /dev/null @@ -1,51 +0,0 @@ -module CryptCheck - class Status - LEVELS = %i(best perfect good warning error critical).freeze - PROBLEMS = %i(warning error critical).freeze - - extend Enumerable - - def self.each(&block) - LEVELS.each &block - end - - def self.empty - self.collect { |s| [s, []] }.to_h - end - - def self.status(statuses) - statuses = self.convert statuses - self.min LEVELS, statuses - end - - class << self - alias_method :'[]', :status - end - - def self.problem(statuses) - statuses = self.convert statuses - self.min PROBLEMS, statuses - end - - def self.sort(statuses) - statuses.sort { |a, b| self.compare a, b } - end - - def self.compare(a, b) - LEVELS.find_index(a.status) <=> LEVELS.find_index(b.status) - end - - private - def self.convert(statuses) - statuses = [statuses] unless statuses.respond_to? :first - first = statuses.first - statuses = statuses.collect &:status if first.respond_to? :status - statuses - end - - def self.min(levels, statuses) - return nil if statuses.empty? - (levels & statuses).last - end - end -end diff --git a/lib/cryptcheck/statused.rb b/lib/cryptcheck/statused.rb deleted file mode 100644 index 2411105..0000000 --- a/lib/cryptcheck/statused.rb +++ /dev/null @@ -1,48 +0,0 @@ -module CryptCheck - module Statused - def status - @status ||= calculate_status - end - - private - def merge(statuses) - Status.collect do |s| - status = statuses.collect { |ss| ss[s] } - status = status.inject &:+ - [s, status.uniq] - end.to_h - end - - def checks - [] - end - - def children - [] - end - - def perform_check(check) - name, check, level = check - result = check.call self - return nil unless result - level ||= result - [level, name] - end - - def personal_status - states = Status.empty - checks.each do |check| - level, name = perform_check check - next unless level - states[level] << name - end - states - end - - def calculate_status - children_statuses = children.collect(&:status) - statuses = [personal_status] + children_statuses - merge statuses - end - end -end diff --git a/lib/cryptcheck/tls/cert.rb b/lib/cryptcheck/tls/cert.rb index dafca2a..e620837 100644 --- a/lib/cryptcheck/tls/cert.rb +++ b/lib/cryptcheck/tls/cert.rb @@ -107,7 +107,7 @@ module CryptCheck @cert.issuer end - include ::CryptCheck::Statused + include ::CryptCheck::State CHECKS = [:weak_sign, -> (s) do not (SIGNATURE_ALGORITHMS_X509[s.signature_algorithm] & WEAK_SIGN).empty? diff --git a/lib/cryptcheck/tls/fixture.rb b/lib/cryptcheck/tls/fixture.rb index bf10ad3..d76c476 100644 --- a/lib/cryptcheck/tls/fixture.rb +++ b/lib/cryptcheck/tls/fixture.rb @@ -17,7 +17,7 @@ class ::OpenSSL::PKey::EC "ECC #{self.size} bits" end - include ::CryptCheck::Statused + include ::CryptCheck::State CHECKS = [ [:weak_key, -> (s) do @@ -50,7 +50,7 @@ class ::OpenSSL::PKey::RSA "RSA #{self.size} bits" end - include ::CryptCheck::Statused + include ::CryptCheck::State CHECKS = [ [:weak_key, -> (s) do @@ -81,7 +81,7 @@ class ::OpenSSL::PKey::DSA "DSA #{self.size} bits" end - include ::CryptCheck::Statused + include ::CryptCheck::State CHECKS = [ [:weak_key, -> (_) { :critical }] @@ -105,7 +105,7 @@ class ::OpenSSL::PKey::DH "DH #{self.size} bits" end - include ::CryptCheck::Statused + include ::CryptCheck::State CHECKS = [ [:weak_dh, -> (s) do diff --git a/lib/cryptcheck/tls/server.rb b/lib/cryptcheck/tls/server.rb index d788cc1..b9bc944 100644 --- a/lib/cryptcheck/tls/server.rb +++ b/lib/cryptcheck/tls/server.rb @@ -69,7 +69,7 @@ module CryptCheck @cert.extensions.any? { |e| e.oid == '1.3.6.1.5.5.7.1.24' } end - include Statused + include State CHECKS = [ # Protocols diff --git a/spec/cryptcheck/status_spec.rb b/spec/cryptcheck/status_spec.rb index 2147a8b..44310cd 100644 --- a/spec/cryptcheck/status_spec.rb +++ b/spec/cryptcheck/status_spec.rb @@ -1,9 +1,9 @@ require 'ostruct' -describe CryptCheck::Status do +describe CryptCheck::State do describe '::status' do it 'must handle empty list' do - expect(CryptCheck::Status.status []).to be_nil + expect(CryptCheck::State.status []).to be_nil end it 'must answer correctly' do @@ -56,7 +56,7 @@ describe CryptCheck::Status do [:best, :perfect] => :perfect, [:best, :best] => :best }.each do |levels, result| - got = CryptCheck::Status.status levels + got = CryptCheck::State.status levels expect(got).to be(result), "#{levels} : expected #{result.inspect}, got #{got.inspect}" end end @@ -64,7 +64,7 @@ describe CryptCheck::Status do it 'must handle object list' do critical = OpenStruct.new status: :critical warning = OpenStruct.new status: :warning - expect(CryptCheck::Status.status [critical, warning]).to be :critical + expect(CryptCheck::State.status [critical, warning]).to be :critical end end @@ -119,7 +119,7 @@ describe CryptCheck::Status do [:best, :perfect] => nil, [:best, :best] => nil }.each do |levels, result| - got = CryptCheck::Status.problem levels + got = CryptCheck::State.problem levels expect(got).to be(result), "#{levels} : expected #{result.inspect}, got #{got.inspect}" end end @@ -127,7 +127,137 @@ describe CryptCheck::Status do it 'must handle object list' do critical = OpenStruct.new status: :critical warning = OpenStruct.new status: :warning - expect(CryptCheck::Status.problem [critical, warning]).to be :critical + expect(CryptCheck::State.problem [critical, warning]).to be :critical + end + end + + describe '#states' do + def match_states(actual, **expected) + expected = ::CryptCheck::State.empty.merge expected + expect(actual.states).to eq expected + end + + let(:empty) do + Class.new do + include ::CryptCheck::State + + def checks + [] + end + end.new + end + let(:childless) do + Class.new do + include ::CryptCheck::State + + def checks + [ + [:foo, -> (_) { true }, :critical], + [:bar, -> (_) { :error }], + [:baz, -> (_) { false }] + ] + end + end.new + end + let(:parent) do + child = Class.new do + include ::CryptCheck::State + + def checks + [[:bar, -> (_) { :error }]] + end + end.new + Class.new do + include ::CryptCheck::State + + def initialize(child) + @child = child + end + + def checks + [[:foo, -> (_) { :critical }]] + end + + def children + [@child] + end + end.new(child) + end + let(:duplicated) do + child = Class.new do + include ::CryptCheck::State + + def checks + [[:foo, -> (_) { :critical }]] + end + end.new + Class.new do + include ::CryptCheck::State + + def initialize(child) + @child = child + end + + def checks + [[:foo, -> (_) { :critical }]] + end + + def children + [@child] + end + end.new(child) + end + + it 'must return empty if no check nor child' do + match_states empty + end + + it 'must return personal status if no child' do + match_states childless, critical: %i(foo), error: %i(bar) + end + + it 'must return personal and children statuses' do + match_states parent, critical: %i(foo), error: %i(bar) + end + + it 'must return remove duplicated status' do + match_states duplicated, critical: %i(foo) + end + end + + describe '#status' do + it 'must return nil if nothing special' do + empty = Class.new do + include ::CryptCheck::State + + def checks + [] + end + end.new + expect(empty.status).to be_nil + end + + it 'must return the status if only one' do + empty = Class.new do + include ::CryptCheck::State + + def checks + [[:foo, -> (_) { :critical }]] + end + end.new + expect(empty.status).to be :critical + end + + it 'must return the worst status if multiple' do + empty = Class.new do + include ::CryptCheck::State + + def checks + [[:foo, -> (_) { :critical }], + [:bar, -> (_) { :error }]] + end + end.new + expect(empty.status).to be :critical end end end diff --git a/spec/cryptcheck/statused_spec.rb b/spec/cryptcheck/statused_spec.rb deleted file mode 100644 index a53dabb..0000000 --- a/spec/cryptcheck/statused_spec.rb +++ /dev/null @@ -1,82 +0,0 @@ -describe CryptCheck::Statused do - def match_status(actual, **expected) - expected = ::CryptCheck::Status.empty.merge expected - expect(actual.status).to eq expected - end - - describe '::status' do - it 'must return empty if no check nor child' do - statused = Class.new do - include ::CryptCheck::Statused - end.new - match_status statused - end - - it 'must return personal status if no child' do - statused = Class.new do - include ::CryptCheck::Statused - - def checks - [ - [:foo, -> (_) { true }, :critical], - [:bar, -> (_) { :error }], - [:baz, -> (_) { false }] - ] - end - end.new - match_status statused, critical: %i(foo), error: %i(bar) - end - - it 'must return personal and children statuses' do - child = Class.new do - include ::CryptCheck::Statused - - def checks - [[:bar, -> (_) { :error }]] - end - end.new - parent = Class.new do - include ::CryptCheck::Statused - - def initialize(child) - @child = child - end - - def checks - [[:foo, -> (_) { :critical }]] - end - - def children - [@child] - end - end.new(child) - match_status parent, critical: %i(foo), error: %i(bar) - end - - it 'must return remove duplicated status' do - child = Class.new do - include ::CryptCheck::Statused - - def checks - [[:foo, -> (_) { :critical }]] - end - end.new - parent = Class.new do - include ::CryptCheck::Statused - - def initialize(child) - @child = child - end - - def checks - [[:foo, -> (_) { :critical }]] - end - - def children - [@child] - end - end.new(child) - match_status parent, critical: %i(foo) - end - end -end