pkg/ | |||||
metadata.json | |||||
*.idea | |||||
*.swp | |||||
*.tmp |
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. |
=========== | |||||
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.1.0 |
# == 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 | |||||
# == 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 %} |
# == 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',}, | |||||
# },],} | |||||
# |
{{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') }} |
<?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> |
<?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> | |||||
# == 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 %} |
# 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 |