Skip to content

Commit

Permalink
Merge pull request #20 from dseira/master
Browse files Browse the repository at this point in the history
Added new ng states
  • Loading branch information
dseira authored Feb 20, 2018
2 parents 0f16409 + dd394b4 commit 6eec356
Show file tree
Hide file tree
Showing 8 changed files with 365 additions and 0 deletions.
87 changes: 87 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,90 @@ The ``fail2ban.config`` state also populates the ``jail.local``, ``fail2ban.loca
Gotchas
=======
In the ``pillar.example``, note that the iptable action uses ``port=ssh`` (lowercase), not ``port=SSH`` (uppercase).

Next-generation, alternate approach
===================================

The following states provide an alternate approach to managing fail2ban. Tested in Ubuntu 14/16 and CentOS 6/7.

.. contents::
:local:

``fail2ban.ng``
---------------

Meta state for inclusion of all ng states.

``fail2ban.ng.install``
-----------------------

Install the ``fail2ban`` package.

``fail2ban.ng.config``
----------------------

Configure fail2ban creating a ``jail.local`` file based on pillar data that overrid ``jail.conf``. It also creates a ``file.local`` per action/filter. Either in jails, actions or filters is possible to setup a ``source_path`` options to upload your configuration directly (see ``pillar.example``). It is also possible to remove either actions or filters setting up ``enabled: False`` in it section (see ``pillar.example``).

Keep in mind that in ng states ``lookup``, ``config``, ``jails``, ``actions`` and ``filters`` are at the same level (in the old states, all the sections are under ``lookup``:

.. code-block:: yaml
fail2ban:
ng:
lookup:
config:
jails:
actions:
filters:
Keep in mind also that in ng states change the syntax for the actions and filters adding a new `config` section and `enabled` option (optional):

.. code-block:: yaml
fail2ban:
ng:
actions:
name-of-action:
enabled: True/False # OPTIONAL
config:
Definition:
actionban:
actionunban:
Init:
whatever:
filters:
name-of-filter:
enabled: True/False # OPTIONAL
config:
Definition:
failregex:
It is also possible to specify the source file for config, jails, actions and filters instead of using the template:

.. code-block:: yaml
fail2ban:
ng:
config:
source_path: salt://path-to-fail2ban-config-file
jails:
source_path: salt://path-to-fail2ban-config-file
actions:
name-of-action:
config:
source_path: salt://path-to-action-file
filters:
name-of-filter:
config:
source_path: salt://path-to-filter-file
``fail2ban.ng.service``
-----------------------

Manage fail2ban service. It is also possible to disable the service using the following pillar configuration:

.. code-block:: yaml
fail2ban:
ng:
enabled: False
116 changes: 116 additions & 0 deletions fail2ban/ng/config.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
# vim: ft=sls

{% from "fail2ban/ng/map.jinja" import fail2ban with context %}
fail2ban.ng.config.fail2ban:
{% if fail2ban.config is defined %}
{% if fail2ban.config.source_path is defined %}
{% set fail2ban_config = fail2ban.config.source_path %}
{% else %}
{% set fail2ban_config = 'salt://fail2ban/ng/files/config.jinja' %}
{% endif %}
file.managed:
- name: {{ fail2ban.prefix }}/etc/fail2ban/fail2ban.local
- source: {{ fail2ban_config }}
- user: {{ fail2ban.user|default('root') }}
- group: {{ fail2ban.group|default('root') }}
- mode: '{{ fail2ban.mode|default("644")}}'
- template: jinja
{% if fail2ban.config.source_path is not defined %}
- context:
config:
Definition: {{ fail2ban.config|yaml }}
{% endif %}
{% else %}
file.absent:
- name: {{ fail2ban.prefix }}/etc/fail2ban/fail2ban.local
{% endif %}
- watch_in:
- service: {{ fail2ban.service }}
fail2ban.ng.config.jails:
{% if fail2ban.jails is defined %}
{% if fail2ban.jails.source_path is defined %}
{% set fail2ban_jails = fail2ban.jails.source_path %}
{% else %}
{% set fail2ban_jails = 'salt://fail2ban/ng/files/config.jinja' %}
{% endif %}
file.managed:
- name: {{ fail2ban.prefix }}/etc/fail2ban/jail.local
- source: {{ fail2ban_jails }}
- user: {{ fail2ban.user|default('root') }}
- group: {{ fail2ban.group|default('root') }}
- mode: '{{ fail2ban.mode|default("644")}}'
- template: jinja
{% if fail2ban.jails.source_path is not defined %}
- context:
config: {{ fail2ban.jails|yaml }}
{% endif %}
{% else %}
file.absent:
{% endif %}
- watch_in:
- service: {{ fail2ban.service }}
{% for name, options in fail2ban.actions|dictsort %}
{% if options.config.source_path is defined %}
{% set fail2ban_actions = options.config.source_path %}
{% else %}
{% set fail2ban_actions = 'salt://fail2ban/ng/files/config.jinja' %}
{% endif %}
fail2ban.ng.config.action.{{ name }}:
{% if ( 'enabled' in options and options.enabled ) or ('enabled' not in options ) %}
file.managed:
- name: {{ fail2ban.prefix }}/etc/fail2ban/action.d/{{ name }}.local
- source: {{ fail2ban_actions }}
- user: {{ fail2ban.user|default('root') }}
- group: {{ fail2ban.group|default('root') }}
- mode: '{{ fail2ban.mode|default("644")}}'
- template: jinja
- watch_in:
- service: {{ fail2ban.service }}
{% if options.config.source_path is not defined %}
- context:
config: {{ options.config|yaml }}
{% endif %}
{% elif 'enabled' in options and not options.enabled %}
file.absent:
- name: {{ fail2ban.prefix }}/etc/fail2ban/action.d/{{ name }}.local
{% endif %}
{% endfor %}
{% for name, options in fail2ban.filters|dictsort %}
{% if options.config.source_path is defined %}
{% set fail2ban_filters = options.config.source_path %}
{% else %}
{% set fail2ban_filters = 'salt://fail2ban/ng/files/config.jinja' %}
{% endif %}
fail2ban.ng.config.filter.{{ name }}:
{% if ( 'enabled' in options and options.enabled ) or ('enabled' not in options ) %}
file.managed:
- name: {{ fail2ban.prefix }}/etc/fail2ban/filter.d/{{ name }}.local
- source: {{ fail2ban_filters }}
- user: {{ fail2ban.user|default('root') }}
- group: {{ fail2ban.group|default('root') }}
- mode: '{{ fail2ban.mode|default("644")}}'
- template: jinja
- watch_in:
- service: {{ fail2ban.service }}
{% if options.config.source_path is not defined %}
- context:
config: {{ options.config|yaml }}
{% endif %}
{% elif 'enabled' in options and not options.enabled %}
file.absent:
- name: {{ fail2ban.prefix }}/etc/fail2ban/filter.d/{{ name }}.local
{% endif %}
{% endfor %}
26 changes: 26 additions & 0 deletions fail2ban/ng/files/config.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#
# This file is managed by salt. Do not edit by hand.
#
{% macro print_config(name, value) %}
{%- set name_length = name|length %}
{%- if value is string %}
{{ name }} = {{ value }}
{%- elif value is number %}
{{ name }} = {{ value }}
{%- else %}
{#- Since strings are also sequences, there's no way to explicitly test for lists #}
{{ name }} = {{ value|first }}
{%- if value|length > 1 %}
{%- for item in value[1:] %}
{{ item|indent(width=name_length + 3, indentfirst=True) }}
{%- endfor %}
{%- endif %}
{%- endif %}
{%- endmacro %}

{%- for section, section_data in config|dictsort %}
[{{section}}]
{%- for name, value in section_data|dictsort %}
{{- print_config(name, value) }}
{%- endfor %}
{% endfor %}
7 changes: 7 additions & 0 deletions fail2ban/ng/init.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# vim: ft=sls

include:
- fail2ban.ng.install
- fail2ban.ng.config
- fail2ban.ng.service
8 changes: 8 additions & 0 deletions fail2ban/ng/install.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
# vim: ft=sls

{% from "fail2ban/ng/map.jinja" import fail2ban with context %}
fail2ban.ng.install:
pkg.installed:
- name: {{ fail2ban.package }}
30 changes: 30 additions & 0 deletions fail2ban/ng/map.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# vim: ft=jinja

{% set os_family_map = salt['grains.filter_by']({
'FreeBSD': {
'package': 'py27-fail2ban',
'service': 'fail2ban',
'prefix': '/usr/local',
},
'Gentoo': {
'package': 'net-analyzer/fail2ban',
'service': 'fail2ban',
'prefix': '',
},
'default': {
'package': 'fail2ban',
'service': 'fail2ban',
'prefix': '',
'user': 'root',
'group': 'root',
'mode': '644',
},
}, merge=salt['pillar.get']('fail2ban:lookup')) %}

{% set fail2ban = salt['pillar.get'](
'fail2ban:ng',
default=os_family_map,
merge=True
)
%}
17 changes: 17 additions & 0 deletions fail2ban/ng/service.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
# vim: ft=sls

{% from "fail2ban/ng/map.jinja" import fail2ban with context %}
fail2ban.ng.service:
{% if ( 'enabled' in fail2ban and fail2ban.enabled ) or ('enabled' not in fail2ban ) %}
service.running:
- name: {{ fail2ban.service }}
- enable: True
- require:
- pkg: {{ fail2ban.package }}
{% elif 'enabled' in fail2ban and not fail2ban.enabled %}
service.dead:
- name: {{ fail2ban.service }}
- enable: False
{% endif %}
74 changes: 74 additions & 0 deletions pillar.example
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,77 @@ fail2ban:
nginx-noscript:
Definition:
failregex: <HOST>.*(GET|POST).*(\.php|\.asp|\.exe|\.pl|\.cgi|\.scgi).*

#
# New NG states
#
ng:
lookup:
prefix: '/opt'
package: 'fail2ban-new-package'

# fail2ban.local
config:

# FTP-style
source_path: salt://path-to-fail2ban-file

# Template-style
loglevel: ERROR
logtarget: /var/log/fail2ban.log

# jail.local
jails:

# FTP-style
source_path: salt://path-to-jail-file

# Template-style
DEFAULT:
ignoreip: 127.0.0.1
bantime: 600
ssh:
actions: iptables[name=SSH, port=ssh, protocol=tcp]
enabled: 'true'
filter: sshd
logpath: /var/log/auth.log
maxretry: 6
port: ssh
ssh_ddos:
action: iptables[name=SSH, port=ssh, protocol=tcp]
enabled: 'true'
filter: sshd-ddos
logpath: /var/log/auth.log
maxretry: 6
port: ssh

# action.d
actions:

# Template-style
csf-ip-deny:
enabled: True # OPTIONAL, default True; if False, the action.d/csf-ip-deny.local action will be deleted
config:
Definition:
actionban: csf -d <ip> Added by Fail2Ban for <name>
actionunban: csf -dr <ip>

# FTP-style
test-action:
config:
source_path: salt://path-to-action-file

# filter.d
filters:

# Template-style
nginx-noscript:
enabled: True # OPTIONAL, default True; if False, the filter.d/nginx-noscript.local will be deleted
config:
Definition:
failregex: <HOST>.*(GET|POST).*(\.php|\.asp|\.exe|\.pl|\.cgi|\.scgi).*

# FTP-style
test-filter:
config:
source_path: salt://path-to-filter-file

0 comments on commit 6eec356

Please sign in to comment.