@@ -0,0 +1,5 @@ | |||
pkg/ | |||
metadata.json | |||
*.idea | |||
*.swp | |||
*.tmp |
@@ -0,0 +1,20 @@ | |||
Copyright (c) 2014 David Bezuidenhout <tinuva@ipv6.za.org> | |||
NOTICE THE LICENSE EXCEPTIONS BELOW. | |||
Licensed under the Apache License, Version 2.0 (the "License"); | |||
you may not use this file except in compliance with the License. | |||
You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
EXCEPTIONS: | |||
You MAY NOT upload parts or the whole work of this product on Github or | |||
any other platform again UNLESS you are in possession of an agreement | |||
by the author OR use the function called "FORK" provided on Github itself. | |||
Other parts of the specified license above are not affected. |
@@ -0,0 +1,68 @@ | |||
=========== | |||
firewalld-formula | |||
=========== | |||
Salt Stack Formula to set up and configure Firewalld, dynamically managed firewall with support for network/firewall zones to define the trust level of network connections or interfaces | |||
NOTICE BEFORE YOU USE | |||
===================== | |||
* This formula aims to follow the conventions and recommendations described at http://docs.saltstack.com/topics/conventions/formulas.html | |||
TODO | |||
==== | |||
* configure local pre-commit hooks (code syntax check based on file extension, check for ugly *utf-8 mac os white space*) | |||
Instructions | |||
============ | |||
1. Add this repository as a `GitFS <http://docs.saltstack.com/topics/tutorials/gitfs.html>`_ backend in your Salt master config. | |||
2. Configure your Pillar top file (``/srv/pillar/top.sls``), see pillar.example | |||
3. Include this Formula within another Formula or simply define your needed states within the Salt top file (``/srv/salt/top.sls``). | |||
Available states | |||
================ | |||
.. contents:: | |||
:local: | |||
``firewalld`` | |||
------- | |||
Manage firewalld | |||
Additional resources | |||
==================== | |||
None | |||
Formula Dependencies | |||
==================== | |||
None | |||
Contributions | |||
============= | |||
Contributions are always welcome. All development guidelines you have to know are | |||
* write clean code (proper YAML+Jinja syntax, no trailing whitespaces, no empty lines with whitespaces, LF only) | |||
* set sane default settings | |||
* test your code | |||
* update README.rst doc | |||
Salt Compatibility | |||
================== | |||
Tested with: | |||
* 2014.1.x | |||
OS Compatibility | |||
================ | |||
Tested with: | |||
* CentOS 7 |
@@ -0,0 +1 @@ | |||
0.1.0 |
@@ -0,0 +1,29 @@ | |||
# == State: firewalld._config | |||
# | |||
# This state configures firewalld. | |||
# | |||
/etc/firewalld/: | |||
file.directory: # make sure this is a directory | |||
- user: root | |||
- group: root | |||
- mode: 750 | |||
- require: | |||
- pkg: firewalld # make sure package is installed | |||
- watch_in: | |||
- service: firewalld # restart service | |||
/etc/firewalld/firewalld.conf: | |||
file: | |||
- managed | |||
- name: /etc/firewalld/firewalld.conf | |||
- user: root | |||
- group: root | |||
- mode: 640 | |||
- source: salt://firewalld/files/firewalld.conf | |||
- template: jinja | |||
- require: | |||
- pkg: firewalld # make sure package is installed | |||
- watch_in: | |||
- service: firewalld # restart service | |||
@@ -0,0 +1,41 @@ | |||
# == State: firewalld._service | |||
# | |||
# This state ensures that /etc/firewalld/services/ exists. | |||
# | |||
/etc/firewalld/services: | |||
file.directory: # make sure this is a directory | |||
- user: root | |||
- group: root | |||
- mode: 750 | |||
- require: | |||
- pkg: firewalld # make sure package is installed | |||
- watch_in: | |||
- service: firewalld # restart service | |||
# == Define: firewalld._service | |||
# | |||
# This defines a service configuration, see firewalld.service (5) man page. | |||
# You usually don't need this, you can simply add ports to zone. | |||
{% for k, v in salt['pillar.get']('firewalld:services', {}).items() %} | |||
{% set s_name = v.name|default(k) %} | |||
/etc/firewalld/services/{{ s_name }}.xml: | |||
file: | |||
- managed | |||
- name: /etc/firewalld/services/{{ s_name }}.xml | |||
- user: root | |||
- group: root | |||
- mode: 644 | |||
- source: salt://firewalld/files/service.xml | |||
- template: jinja | |||
- require: | |||
- pkg: firewalld # make sure package is installed | |||
- watch_in: | |||
- service: firewalld # restart service | |||
- context: | |||
name: {{ s_name }} | |||
service: {{ v }} | |||
{% endfor %} |
@@ -0,0 +1,140 @@ | |||
# == State: firewalld._zone | |||
# | |||
# This state ensures that /etc/firewalld/zones/ exists. | |||
# | |||
/etc/firewalld/zones: | |||
file.directory: # make sure this is a directory | |||
- user: root | |||
- group: root | |||
- mode: 750 | |||
- require: | |||
- pkg: firewalld # make sure package is installed | |||
- watch_in: | |||
- service: firewalld # restart service | |||
# == Define: firewalld._zone | |||
# | |||
# This defines a zone configuration, see firewalld.zone (5) man page. | |||
# | |||
{% for k, v in salt['pillar.get']('firewalld:zones', {}).items() %} | |||
{% set z_name = v.name|default(k) %} | |||
/etc/firewalld/zones/{{ z_name }}.xml: | |||
file: | |||
- managed | |||
- name: /etc/firewalld/zones/{{ z_name }}.xml | |||
- user: root | |||
- group: root | |||
- mode: 644 | |||
- source: salt://firewalld/files/zone.xml | |||
- template: jinja | |||
- require: | |||
- pkg: firewalld # make sure package is installed | |||
- watch_in: | |||
- service: firewalld # restart service | |||
- context: | |||
name: {{ z_name }} | |||
zone: {{ v }} | |||
{% endfor %} | |||
# === Parameters | |||
# | |||
# [*target*] can be one of {'ACCEPT', '%%REJECT%%', 'DROP'}. | |||
# Used to accept, reject or drop every packet that | |||
# doesn't match any rule (port, service, etc.). | |||
# Default (when target is not specified) is reject. | |||
# [*short*] short readable name | |||
# [*description*] long description of zone | |||
# [*interfaces*] list of interfaces to bind to a zone | |||
# [*sources*] list of source addresses or source address | |||
# ranges ("address/mask") to bind to a zone | |||
# [*ports*] | |||
# list of ports to open | |||
# ports => [{ | |||
# comment => optional, string | |||
# port => mandatory, string, e.g. '1234' | |||
# protocol => mandatory, string, e.g. 'tcp' },...] | |||
# [*services*] list of predefined firewalld services | |||
# [*icmp_blocks*] list of predefined icmp-types to block | |||
# [*masquerade*] enable masquerading ? | |||
# [*forward_ports*] | |||
# list of ports to forward to other port and/or machine | |||
# forward_ports => [{ | |||
# comment => optional, string | |||
# portid => mandatory, string, e.g. '123' | |||
# protocol => mandatory, string, e.g. 'tcp' | |||
# to_port => mandatory to specify either to_port or/and to_addr | |||
# to_addr => mandatory to specify either to_port or/and to_addr },...] | |||
# [*rich_rules*] | |||
# list of rich language rules (firewalld.richlanguage(5)) | |||
# You have to specify one (and only one) | |||
# of {service, port, protocol, icmp_block, masquerade, forward_port} | |||
# and one (and only one) of {accept, reject, drop} | |||
# family - 'ipv4' or 'ipv6', optional, see Rule in firewalld.richlanguage(5) | |||
# source => { optional, see Source in firewalld.richlanguage(5) | |||
# address => mandatory, string, e.g. '192.168.1.0/24' | |||
# invert => optional, bool, e.g. true } | |||
# destination => { optional, see Destination in firewalld.richlanguage(5) | |||
# address => mandatory, string | |||
# invert => optional, bool, e.g. true } | |||
# service - string, see Service in firewalld.richlanguage(5) | |||
# port => { see Port in firewalld.richlanguage(5) | |||
# portid => mandatory | |||
# protocol => mandatory } | |||
# protocol - string, see Protocol in firewalld.richlanguage(5) | |||
# icmp_block - string, see ICMP-Block in firewalld.richlanguage(5) | |||
# masquerade - bool, see Masquerade in firewalld.richlanguage(5) | |||
# forward_port => { see Forward-Port in firewalld.richlanguage(5) | |||
# portid => mandatory | |||
# protocol => mandatory | |||
# to_port => mandatory to specify either to_port or/and to_addr | |||
# to_addr => mandatory to specify either to_port or/and to_addr } | |||
# log => { see Log in firewalld.richlanguage(5) | |||
# prefix => string, optional | |||
# level => string, optional | |||
# limit => string, optional } | |||
# audit => { see Audit in firewalld.richlanguage(5) | |||
# limit => string, optional } | |||
# accept - any value, e.g. true, see Action in firewalld.richlanguage(5) | |||
# reject => { see Action in firewalld.richlanguage(5) | |||
# type => string, optional } | |||
# drop - any value, e.g. true, see Action in firewalld.richlanguage(5) | |||
# | |||
# === Examples | |||
# | |||
# firewalld::zone { "custom": | |||
# description => "This is an example zone", | |||
# services => ["ssh", "dhcpv6-client"], | |||
# ports => [{ | |||
# comment => "for our dummy service", | |||
# port => "1234", | |||
# protocol => "tcp",},], | |||
# masquerade => true, | |||
# forward_ports => [{ | |||
# comment => 'forward 123 to other machine', | |||
# portid => '123', | |||
# protocol => 'tcp', | |||
# to_port => '321', | |||
# to_addr => '1.2.3.4',},], | |||
# rich_rules => [{ | |||
# family => 'ipv4', | |||
# source => { | |||
# address => '192.168.1.0/24', | |||
# invert => true,}, | |||
# port => { | |||
# portid => '123-321', | |||
# protocol => 'udp',}, | |||
# log => { | |||
# prefix => 'local', | |||
# level => 'notice', | |||
# limit => '3/s',}, | |||
# audit => { | |||
# limit => '2/h',}, | |||
# reject => { | |||
# type => 'icmp-host-prohibited',}, | |||
# },],} | |||
# |
@@ -0,0 +1,35 @@ | |||
{{pillar['headers']['salt']['file']}} | |||
{% set firewalld = pillar.get('firewalld', {}) -%} | |||
# firewalld config file | |||
# default zone | |||
# The default zone used if an empty zone string is used. | |||
# Default: public | |||
DefaultZone={{ firewalld.default_zone|default('public') }} | |||
# Minimal mark | |||
# Marks up to this minimum are free for use for example in the direct | |||
# interface. If more free marks are needed, increase the minimum | |||
# Default: 100 | |||
MinimalMark={{ firewalld.minimal_mark|default('100') }} | |||
# Clean up on exit | |||
# If set to no or false the firewall configuration will not get cleaned up | |||
# on exit or stop of firewalld | |||
# Default: yes | |||
CleanupOnExit={{ firewalld.cleanup_on_exit|default('yes') }} | |||
# Lockdown | |||
# If set to enabled, firewall changes with the D-Bus interface will be limited | |||
# to applications that are listed in the lockdown whitelist. | |||
# The lockdown whitelist file is lockdown-whitelist.xml | |||
# Default: no | |||
Lockdown={{ firewalld.lockdown|default('no') }} | |||
# IPv6_rpfilter | |||
# Performs a reverse path filter test on a packet for IPv6. If a reply to the | |||
# packet would be sent via the same interface that the packet arrived on, the | |||
# packet will match and be accepted, otherwise dropped. | |||
# The rp_filter for IPv4 is controlled using sysctl. | |||
# Default: yes | |||
IPv6_rpfilter={{ firewalld.IPv6_rpfilter|default('yes') }} |
@@ -0,0 +1,25 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
{{pillar['headers']['salt']['xml']}} | |||
<service> | |||
{% if 'short' in service %}<short>{{ service.short }}</short>{% else %}<short>{{ name }}</short>{% endif %} | |||
{% if 'description' in service %}<description>{{ service.description }}</description>{% endif %} | |||
{% if 'ports' in service %} | |||
{% if 'tcp' in service.ports %} | |||
{% for v in service.ports.tcp %}<port port="{{ v }}" protocol="tcp" />{% endfor %} | |||
{% endif %} | |||
{% if 'udp' in service.ports %} | |||
{% for v in service.ports.udp %}<port port="{{ v }}" protocol="udp" />{% endfor %} | |||
{% endif %} | |||
{% if 'modules' in service %} | |||
{% for v in service.modules %}<module name="{{ v }}" />{% endfor %} | |||
{% endif %} | |||
{% endif %} | |||
{% if 'destinations' in service %} | |||
{% if 'ipv4' in service.destinations %} | |||
{% for v in service.destinations.ipv4 %}<destination ipv4="{{ v }}" />{% endfor %} | |||
{% endif %} | |||
{% if 'ipv6' in service.destinations %} | |||
{% for v in service.destinations.ipv6 %}<destination ipv6="{{ v }}" />{% endfor %} | |||
{% endif %} | |||
{% endif %} | |||
</service> |
@@ -0,0 +1,97 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
{{pillar['headers']['salt']['xml']}} | |||
<zone{% if 'target' in zone %} target="{{ zone.target }}"{% endif %}> | |||
{% if 'short' in zone %}<short>{{ zone.short }}</short>{% else %}<short>{{ name }}</short>{% endif %} | |||
{% if 'description' in zone %}<description>{{ zone.description }}</description>{% endif %} | |||
{% if 'interfaces' in zone %} | |||
{% for v in zone.interfaces %}<interface name="{{ v }}" />{% endfor %} | |||
{% endif %} | |||
{% if 'sources' in zone %} | |||
{% for v in zone.sources %}<source name="{{ v }}" />{% endfor %} | |||
{% endif %} | |||
{% if 'services' in zone %} | |||
{% for v in zone.services %}<service name="{{ v }}" />{% endfor %} | |||
{% endif %} | |||
{% if 'ports' in zone %} | |||
{% for v in zone.ports %} | |||
{% if 'comment' in v %} | |||
<!-- {{ v.comment }} --> | |||
{% endif %} | |||
<port port="{{ v.port }}" protocol="{{ v.protocol }}"/> | |||
{% endfor %} | |||
{% endif %} | |||
{% if 'icmp_blocks' in zone %} | |||
{% for v in zone.icmp_blocks %}<icmp-block name="{{ v }}" />{% endfor %} | |||
{% endif %} | |||
{% if 'masquerade' in zone %}{% if zone.masquerade %}<masquerade/>{% endif %}{% endif %} | |||
{% if 'forward_ports' in zone %} | |||
{% for v in zone.forward_ports %} | |||
{% if 'comment' in v %} | |||
<!-- {{ v.comment }} --> | |||
{% endif %} | |||
<forward-port port="{{ v.portid }}" protocol="{{ v.protocol }}"{% if 'to_port' in v %} to-port="{{ v.to_port }}"{% endif %}{% if 'to_addr' in v %} to-addr="{{ v.to_addr }}"{% endif %} /> | |||
{% endfor %} | |||
{% endif %} | |||
{% if 'rich_rules' in zone %} | |||
{% for rule in zone.rich_rules %} | |||
{% if 'family' in rule %} | |||
<rule family="{{ rule.family }}"> | |||
{% else %} | |||
<rule> | |||
{% endif %} | |||
{% if 'source' in rule %} | |||
<source address="{{ rule.source.address }}" {% if 'invert' in rule.source %}invert="{{ rule.source.invert }}"{% endif %}/> | |||
{% endif %} | |||
{% if 'destination' in rule %} | |||
<destination address="{{ rule.destination.address }}" {% if 'invert' in rule.destination %}invert="{{ rule.destination.invert }}"{% endif %}/> | |||
{% endif %} | |||
{% if 'service' in rule %} | |||
<destination name="{{ rule.service }}"/> | |||
{% endif %} | |||
{% if 'port' in rule %} | |||
<port port="{{ rule.port.portid }}" protocol="{{ rule.port.protocol }}"/> | |||
{% endif %} | |||
{% if 'protocol' in rule %} | |||
<protocol value="{{ rule.protocol }}"/> | |||
{% endif %} | |||
{% if 'icmp_block' in rule %} | |||
<icmp_block name="{{ rule.icmp_block }}"/> | |||
{% endif %} | |||
{% if 'masquerade' in rule %} | |||
{% if rule.masquerade %}<masquerade/>{% endif %} | |||
{% endif %} | |||
{% if 'forward_port' in rule %} | |||
{% if 'comment' in rule.forward_port %} | |||
<!-- {{ rule.forward_port.comment }} --> | |||
{% endif %} | |||
<forward-port port="{{ rule.forward_port.portid }}" protocol="{{ rule.forward_port.protocol }}"{% if 'to_port' in rule.forward_port %} to-port="{{ rule.forward_port.to_port }}"{% endif %}{% if 'to_addr' in rule.forward_port %} to-addr="{{ rule.forward_port.to_addr }}"{% endif %} /> | |||
{% endif %} | |||
{% if 'log' in rule %} | |||
<log{% if 'prefix' in rule.log %} prefix="{{ rule.log.prefix }}"{% endif %}{% if 'level' in rule.log %} level="{{ rule.log.level }}"{% endif %}> | |||
{% if 'limit' in rule.log %} | |||
<limit value="{{ rule.log.limit }}"/> | |||
{% endif %} | |||
</log> | |||
{% endif %} | |||
{% if 'audit' in rule %} | |||
<audit>{% if 'limit' in rule.audit %} <limit value="{{ rule.audit.limit }}"/>{% endif %}</audit> | |||
{% endif %} | |||
{% if 'accept' in rule %} | |||
<accept/> | |||
{% endif %} | |||
{% if 'reject' in rule %} | |||
<reject{% if 'type' in rule.reject %} type="{{ rule.reject.type }}"{% endif %}/> | |||
{% endif %} | |||
{% if 'drop' in rule %} | |||
<drop/> | |||
{% endif %} | |||
</rule> | |||
{% endfor %} | |||
{% endif %} | |||
</zone> | |||
@@ -0,0 +1,41 @@ | |||
# == State: firewalld | |||
# | |||
# This state installs/runs firewalld. | |||
# | |||
{% if salt['pillar.get']('firewalld:enabled') %} | |||
include: | |||
- firewalld._config | |||
- firewalld._service | |||
- firewalld._zone | |||
# iptables service that comes with rhel/centos | |||
iptables: | |||
service: | |||
- disabled | |||
- enable: False | |||
ip6tables: | |||
service: | |||
- disabled | |||
- enable: False | |||
firewalld: | |||
pkg: | |||
- installed | |||
service: | |||
- running # ensure it's running | |||
- enable: True # start on boot | |||
- require: | |||
- pkg: firewalld | |||
- file: /etc/firewalld/firewalld.conf # require this file | |||
- service: iptables # ensure it's stopped | |||
- service: ip6tables # ensure it's stopped | |||
{% else %} | |||
firewalld: | |||
service: | |||
- dead # ensure it's not running | |||
- enable: False # don't start on boot | |||
{% endif %} |
@@ -0,0 +1,56 @@ | |||
# CentOS7 FirewallD firewall | |||
firewalld: | |||
enabled: True | |||
default_zone: public | |||
services: | |||
sshcustom: | |||
short: sshcustom | |||
description: SSH on port 3232 and 5252. Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful. | |||
ports: | |||
tcp: | |||
- 3232 | |||
- 5252 | |||
modules: | |||
- some_module_to_load | |||
destinations: | |||
ipv4: | |||
- 224.0.0.251 | |||
- 224.0.0.252 | |||
ipv6: | |||
- ff02::fb | |||
- ff02::fc | |||
zones: | |||
public: | |||
short: Public | |||
description: "For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted." | |||
services: | |||
- http | |||
- https | |||
- ssh | |||
- dhcpv6-client | |||
# ports: | |||
# - comment: For our dummy service | |||
# port: 1234 | |||
# protocol: tcp | |||
# forward_ports: | |||
# - comment: forward 123 to other machine | |||
# portid: 123 | |||
# protocol: tcp | |||
# to_port: 321 | |||
# to_addr: 1.2.3.4 | |||
# rich_rules: | |||
# - family: ipv4 | |||
# source: | |||
# address: 192.168.1.0/24 | |||
# invert: true | |||
# port: | |||
# portid: 123-321 | |||
# protocol: udp | |||
# log: | |||
# prefix: local | |||
# level: notice | |||
# limit: 3/s | |||
# audit: | |||
# limit: 2/h | |||
# reject: | |||
# type: icmp-host-prohibited |