diff --git a/.rubocop.yml b/.rubocop.yml index be6de7d..78e345d 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -31,6 +31,9 @@ RSpec/MultipleExpectations: RSpec/SubjectStub: Enabled: false +RSpec/FilePath: + Enabled: false + Style/BlockDelimiters: Exclude: - 'spec/**/*' diff --git a/lib/panda_motd/components/fail_2_ban.rb b/lib/panda_motd/components/fail_2_ban.rb new file mode 100644 index 0000000..faad03a --- /dev/null +++ b/lib/panda_motd/components/fail_2_ban.rb @@ -0,0 +1,45 @@ +require 'pry' +class Fail2Ban < Component + def initialize(motd) + super(motd, 'fail_2_ban') + end + + def process + @results = { + jails: {} + } + + @config['jails'].each do |jail| + status = jail_status(jail) + @results[:jails][jail] = { + total: status[:total], + current: status[:current] + } + end + end + + def to_s + result = "Fail2Ban:\n" + @results[:jails].each do |name, stats| + result += " #{name}:\n" + result += " Total bans: #{stats[:total]}\n" + result += " Current bans: #{stats[:current]}\n" + end + + result.gsub(/\s$/, '') + end + + private + + def jail_status(jail) + cmd_result = `fail2ban-client status #{jail}` + if cmd_result =~ /Sorry but the jail '#{jail}' does not exist/ + @errors << ComponentError.new(self, "Invalid jail name '#{jail}'.") + else + total = cmd_result.match(/Total banned:\s+([0-9]+)/)[1].to_i + current = cmd_result.match(/Currently banned:\s+([0-9]+)/)[1].to_i + end + + { total: total, current: current } + end +end diff --git a/lib/panda_motd/config.rb b/lib/panda_motd/config.rb index 9fbdbda..4a50c92 100644 --- a/lib/panda_motd/config.rb +++ b/lib/panda_motd/config.rb @@ -31,7 +31,8 @@ def self.component_classes uptime: Uptime, ssl_certificates: SSLCertificates, filesystems: Filesystems, - last_login: LastLogin + last_login: LastLogin, + fail_2_ban: Fail2Ban } end diff --git a/lib/panda_motd/default_config.yaml b/lib/panda_motd/default_config.yaml index 32f0a10..073f855 100644 --- a/lib/panda_motd/default_config.yaml +++ b/lib/panda_motd/default_config.yaml @@ -95,6 +95,22 @@ components: # /dev/sda1: Ubuntu # /dev/sdc1: Data + ##### + # Fail2Ban + # Displays fail2ban jail statistics. + # + # Settings + # jails: A list of fail2ban jails to obtain statistics from. The name of the + # jail is the same name used in the `fail2ban-client status jailname`. You + # will get the total banned and currently banned numbers for each jail. + ##### + + # fail_2_ban: + # enabled: true + # jails: + # - sshd + # - anotherjail + ##### # Last Login # Displays previous login information for users. diff --git a/spec/components/fail_2_ban_spec.rb b/spec/components/fail_2_ban_spec.rb new file mode 100644 index 0000000..4475aab --- /dev/null +++ b/spec/components/fail_2_ban_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe Fail2Ban do + context 'with normal config' do + subject(:component) { create(:fail_2_ban) } + + it 'gets statistics' do + stub_system_call(component) + + component.process + + expect(component.results[:jails]).to eq( + 'sshd' => { total: 871, current: 0 } + ) + end + + it 'prints the results' do + stub_system_call(component) + + component.process + results = component.to_s + + expect(results).to include 'Fail2Ban:' + expect(results).to include 'Total bans: 871' + expect(results).to include 'Current bans: 0' + end + end + + context 'with config containing an invalid jail name' do + subject(:component) { + create(:fail_2_ban, settings: { 'jails' => ['asdf'] }) + } + + it 'adds an error to the component' do + stub_system_call( + component, + returns: "Sorry but the jail 'asdf' does not exist" + ) + + component.process + + expect(component.errors.count).to eq 1 + expect(component.errors.first.message).to eq "Invalid jail name 'asdf'." + end + end +end diff --git a/spec/fixtures/components/fail_2_ban/output.txt b/spec/fixtures/components/fail_2_ban/output.txt new file mode 100644 index 0000000..4d0c972 --- /dev/null +++ b/spec/fixtures/components/fail_2_ban/output.txt @@ -0,0 +1,9 @@ +Status for the jail: sshd +|- Filter +| |- Currently failed: 0 +| |- Total failed: 9166 +| `- File list: /var/log/auth.log +`- Actions + |- Currently banned: 0 + |- Total banned: 871 + `- Banned IP list:` diff --git a/spec/fixtures/configs/fail_2_ban.yaml b/spec/fixtures/configs/fail_2_ban.yaml new file mode 100644 index 0000000..57b70e1 --- /dev/null +++ b/spec/fixtures/configs/fail_2_ban.yaml @@ -0,0 +1,5 @@ +components: + fail_2_ban: + enabled: true + jails: + - sshd