Просмотр исходного кода

Formula initial version

tags/v0.2.0
Mario del Pozo 10 лет назад
Родитель
Сommit
3c181286da
5 измененных файлов: 306 добавлений и 0 удалений
  1. +86
    -0
      README.md
  2. +19
    -0
      _modules/ufw.py
  3. +104
    -0
      _states/ufw.py
  4. +39
    -0
      pillar.example
  5. +58
    -0
      ufw/init.sls

+ 86
- 0
README.md Просмотреть файл

@@ -0,0 +1,86 @@
ufw-formula
===========

This module manages your firewall using ufw with pillar configured rules.

See the full [Salt Formulas installation and usage instructions](http://docs.saltstack.com/topics/development/conventions/formulas.html).

Usage
-----

All the configuration for the firewall is done via pillar (pillar.example).

Enable firewall, applying default configuration:
```javascript
ufw:
enabled: True
```

Allow 80/tcp (http) traffic from only two remote addresses:
```
ufw:
services:
http:
protocol: tcp
from_addr:
- 10.0.2.15
- 10.0.2.16
```

Allow 443/tcp (https) traffic from network 10.0.0.0/8 to an specific local ip:
```
ufw:
services:
https:
protocol: tcp
from_addr:
- 10.0.0.0/8
to_addr: 10.0.2.1
```

Allow from a service port:
```
ufw:
services:
smtp:
protocol: tcp
```

Allow from an specific port, by number:
```
ufw:
services:
139:
protocol: tcp
```

Allow from a range of ports, udp:
```
ufw:
services:
"10000:20000":
protocol: udp
```

Allow from two specific ports, udp:
```
ufw:
services:
"30000,40000":
protocol: udp
```

Allow an application defined at /etc/ufw/applications.d/:
```
ufw:
applications:
- OpenSSH
```

Authors
-------

Original state and module based on the work from [Yigal Duppen](https://github.com/publysher/infra-example-nginx/tree/develop).

Salt formula developed by Mario del Pozo.


+ 19
- 0
_modules/ufw.py Просмотреть файл

@@ -0,0 +1,19 @@
"""
Execution module for UFW.
"""
def is_enabled():
cmd = 'ufw status | grep "Status: active"'
out = __salt__['cmd.run'](cmd)
return True if out else False


def set_enabled(enabled):
cmd = 'ufw --force enable' if enabled else 'ufw disable'
__salt__['cmd.run'](cmd)


def add_rule(rule):
cmd = "ufw " + rule
out = __salt__['cmd.run'](cmd)
__salt__['cmd.run']("ufw reload")
return out

+ 104
- 0
_states/ufw.py Просмотреть файл

@@ -0,0 +1,104 @@
from salt.exceptions import CommandExecutionError, CommandNotFoundError
import re
import socket


def _unchanged(name, msg):
return {'name': name, 'result': True, 'comment': msg, 'changes': {}}


def _test(name, msg):
return {'name': name, 'result': None, 'comment': msg, 'changes': {}}


def _error(name, msg):
return {'name': name, 'result': False, 'comment': msg, 'changes': {}}


def _changed(name, msg, **changes):
return {'name': name, 'result': True, 'comment': msg, 'changes': changes}


def _resolve(host):
# pure IP address / netmask IPv4 or IPv6 ?
if re.match(r'^([0-9\.](::))+(/[0-9]+)?$', host):
return

return socket.gethostbyname(host)


def _as_rule(method, app, protocol, from_addr, from_port, to_addr, to_port):
cmd = [method]
if app is not None:
cmd.append(app)
else:
if protocol is not None:
cmd.append("proto")
cmd.append(protocol)

cmd.append("from")
if from_addr is not None:
cmd.append(_resolve(from_addr))
else:
cmd.append("any")

if from_port is not None:
cmd.append("port")
cmd.append(_resolve(from_port))

cmd.append("to")
if to_addr is not None:
cmd.append(to_addr)
else:
cmd.append("any")

if to_port is not None:
cmd.append("port")
cmd.append(to_port)
real_cmd = ' '.join(cmd)
return real_cmd


def enabled(name, **kwargs):
if __salt__['ufw.is_enabled']():
return _unchanged(name, "UFW is already enabled")

if __opts__['test']:
return _test(name, "UFW will be enabled")

try:
__salt__['ufw.set_enabled'](True)
except (CommandExecutionError, CommandNotFoundError) as e:
return _error(name, e.message)

return _changed(name, "UFW is enabled", enabled=True)


def allowed(name, app=None, protocol=None,
from_addr=None, from_port=None, to_addr=None, to_port=None):

rule = _as_rule("allow", app=app, protocol=protocol,
from_addr=from_addr, from_port=from_port, to_addr=to_addr, to_port=to_port)

if __opts__['test']:
return _test(name, "{0}: {1}".format(name, rule))

try:
out = __salt__['ufw.add_rule'](rule)
except (CommandExecutionError, CommandNotFoundError) as e:
return _error(name, e.message)

changes = False
for line in out.split('\n'):
if line.startswith("Skipping"):
continue
if line.startswith("Rule added") or line.startswith("Rules updated"):
changes = True
break
return _error(name, line)

if changes:
return _changed(name, "{0} allowed".format(name), rule=rule)
else:
return _unchanged(name, "{0} was already allowed".format(name))


+ 39
- 0
pillar.example Просмотреть файл

@@ -0,0 +1,39 @@
ufw:

enabled: True

services:

# Allow 80/tcp (http) traffic from only two remote addresses.
http:
protocol: tcp
from_addr:
- 10.0.2.15
- 10.0.2.16

# Allow 443/tcp (https) traffic from network 10.0.0.0/8 to an specific local ip.
https:
protocol: tcp
from_addr:
- 10.0.0.0/8
to_addr: 10.0.2.1

# Allow from a service port.
smtp:
protocol: tcp

# Allow from an specific port, by number.
139:
protocol: tcp

# Allow from a range of ports, udp.
"10000:20000":
protocol: udp

# Allow from two specific ports, udp.
"30000,40000":
protocol: udp

# Allow an application defined at /etc/ufw/applications.d/
applications:
- OpenSSH

+ 58
- 0
ufw/init.sls Просмотреть файл

@@ -0,0 +1,58 @@
# UFW management module
{%- set ufw = pillar.get('ufw', {}) %}
{%- if ufw.get('enabled', False) %}

ufw:
pkg:
- installed
service.running:
- enable: True
ufw:
- enabled
- require:
- pkg: ufw

{%- for service_name, service_details in ufw.get('services', {}).items() %}

{%- for from_addr in service_details.get('from_addr', [None]) %}

{%- set protocol = service_details.get('protocol', None) %}
{%- set from_port = service_details.get('from_port', None) %}
{%- set to_addr = service_details.get('to_addr', None) %}

ufw-svc-{{service_name}}-{{from_addr}}:
ufw.allowed:
- protocol: {{protocol}}
{%- if from_addr != None %}
- from_addr: {{from_addr}}
{%- endif %}
{%- if from_port != None %}
- from_port: "{{from_port}}"
{%- endif %}
{%- if to_addr != None %}
- to_addr: {{to_addr}}
{%- endif %}
- to_port: "{{service_name}}"
- require:
- pkg: ufw

{%- endfor %}

{%- endfor %}

# Applications
{%- for app_name in ufw.get('applications', []) %}

ufw-app-{{app_name}}:
ufw.allowed:
- app: {{app_name}}
- require:
- pkg: ufw

{%- endfor %}

{% else %}
#ufw:
#ufw:
#- disabled
{% endif %}

Загрузка…
Отмена
Сохранить