@@ -11,14 +11,31 @@ language: ruby | |||
services: | |||
- docker | |||
# Make sure the instances listed below match up with | |||
# the `platforms` defined in `kitchen.yml` | |||
env: | |||
matrix: | |||
- DISTRIB=debian:stretch/9 | |||
- DISTRIB=ubuntu:xenial/16.04 | |||
- DISTRIB=ubuntu:bionic/18.04 | |||
- INSTANCE: default-debian-9-2019-2-py3 | |||
- INSTANCE: default-ubuntu-1804-2019-2-py3 | |||
- INSTANCE: default-centos-7-2019-2-py3 | |||
- INSTANCE: default-fedora-29-2019-2-py3 | |||
- INSTANCE: default-opensuse-leap-15-2019-2-py3 | |||
# - INSTANCE: default-debian-9-2018-3-py2 | |||
# - INSTANCE: default-ubuntu-1604-2018-3-py2 | |||
# - INSTANCE: default-centos-7-2018-3-py2 | |||
# - INSTANCE: default-fedora-29-2018-3-py2 | |||
# TODO: Use this when fixed instead of `opensuse-leap-42` | |||
# Ref: https://github.com/netmanagers/salt-image-builder/issues/2 | |||
# - INSTANCE: default-opensuse-leap-15-2018-3-py2 | |||
# - INSTANCE: default-opensuse-leap-42-2018-3-py2 | |||
# - INSTANCE: default-debian-8-2017-7-py2 | |||
# - INSTANCE: default-ubuntu-1604-2017-7-py2 | |||
# - INSTANCE: default-centos-6-2017-7-py2 | |||
# - INSTANCE: default-fedora-28-2017-7-py2 | |||
# - INSTANCE: default-opensuse-leap-42-2017-7-py2 | |||
script: | |||
- bundle exec kitchen test | |||
- bundle exec kitchen verify ${INSTANCE} | |||
jobs: | |||
include: |
@@ -1,32 +1,103 @@ | |||
<% | |||
distrib, infos = ENV.fetch('DISTRIB', 'debian:stretch/9').split(':') | |||
codename, version = infos.split('/') | |||
%> | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=yaml | |||
--- | |||
# For help on this file's format, see https://kitchen.ci/ | |||
driver: | |||
name: docker | |||
use_sudo: false | |||
privileged: true | |||
run_command: /lib/systemd/systemd | |||
provisioner: | |||
name: salt_solo | |||
formula: ufw | |||
# Make sure the platforms listed below match up with | |||
# the `env.matrix` instances defined in `.travis.yml` | |||
platforms: | |||
## SALT 2019.2 | |||
- name: debian-9-2019-2-py3 | |||
driver: | |||
image: netmanagers/salt-2019.2-py3:debian-9 | |||
provision_command: | |||
- apt-get update && apt-get install -y locales | |||
- echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen | |||
- locale-gen en_US.UTF-8 | |||
- name: ubuntu-1804-2019-2-py3 | |||
driver: | |||
image: netmanagers/salt-2019.2-py3:ubuntu-18.04 | |||
- name: centos-7-2019-2-py3 | |||
driver: | |||
image: netmanagers/salt-2019.2-py3:centos-7 | |||
- name: fedora-29-2019-2-py3 | |||
driver: | |||
image: netmanagers/salt-2019.2-py3:fedora-29 | |||
- name: opensuse-leap-15-2019-2-py3 | |||
driver: | |||
image: netmanagers/salt-2019.2-py3:opensuse-leap-15 | |||
run_command: /usr/lib/systemd/systemd | |||
# Install Salt from official repositories | |||
salt_install: apt | |||
salt_version: latest | |||
salt_apt_repo: https://repo.saltstack.com/apt/<%= distrib %>/<%= version %>/amd64 | |||
salt_apt_repo_key: https://repo.saltstack.com/apt/<%= distrib %>/<%= version %>/amd64/latest/SALTSTACK-GPG-KEY.pub | |||
## SALT 2018.3 | |||
- name: debian-9-2018-3-py2 | |||
driver: | |||
image: netmanagers/salt-2018.3-py2:debian-9 | |||
provision_command: | |||
- apt-get update && apt-get install -y locales | |||
- echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen | |||
- locale-gen en_US.UTF-8 | |||
- name: ubuntu-1604-2018-3-py2 | |||
driver: | |||
image: netmanagers/salt-2018.3-py2:ubuntu-16.04 | |||
- name: centos-7-2018-3-py2 | |||
driver: | |||
image: netmanagers/salt-2018.3-py2:centos-7 | |||
- name: fedora-29-2018-3-py2 | |||
driver: | |||
image: netmanagers/salt-2018.3-py2:fedora-29 | |||
# TODO: Use this when fixed instead of `opensuse-leap-42` | |||
# Ref: https://github.com/netmanagers/salt-image-builder/issues/2 | |||
# - name: opensuse-leap-15-2018-3-py2 | |||
# driver: | |||
# image: netmanagers/salt-2018.3-py2:opensuse-leap-15 | |||
# run_command: /usr/lib/systemd/systemd | |||
- name: opensuse-leap-42-2018-3-py2 | |||
driver: | |||
image: netmanagers/salt-2018.3-py2:opensuse-leap-42 | |||
run_command: /usr/lib/systemd/systemd | |||
# Don't install Chef | |||
require_chef: false | |||
## SALT 2017.7 | |||
- name: debian-8-2017-7-py2 | |||
driver: | |||
image: netmanagers/salt-2017.7-py2:debian-8 | |||
provision_command: | |||
- apt-get update && apt-get install -y locales | |||
- echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen | |||
- locale-gen en_US.UTF-8 | |||
- name: ubuntu-1604-2017-7-py2 | |||
driver: | |||
image: netmanagers/salt-2017.7-py2:ubuntu-16.04 | |||
- name: centos-6-2017-7-py2 | |||
driver: | |||
image: netmanagers/salt-2017.7-py2:centos-6 | |||
run_command: /sbin/init | |||
run_options: -v /lib/modules:/lib/modules:ro | |||
- name: fedora-28-2017-7-py2 | |||
driver: | |||
image: netmanagers/salt-2017.7-py2:fedora-28 | |||
- name: opensuse-leap-42-2017-7-py2 | |||
driver: | |||
image: netmanagers/salt-2017.7-py2:opensuse-leap-42 | |||
run_command: /usr/lib/systemd/systemd | |||
# Configure Salt | |||
provisioner: | |||
name: salt_solo | |||
log_level: info | |||
salt_install: none | |||
require_chef: false | |||
formula: ufw | |||
salt_copy_filter: | |||
- .kitchen | |||
- .git | |||
state_top: | |||
base: | |||
'*': | |||
- ufw | |||
pillars: | |||
top.sls: | |||
base: | |||
@@ -67,21 +138,15 @@ provisioner: | |||
protocol: tcp | |||
comment: Allow HTTPS | |||
platforms: | |||
- name: <%= distrib %>-<%= codename %> | |||
driver_config: | |||
image: "<%= distrib %>:<%= codename %>" | |||
platform: <%= distrib %> | |||
provision_command: | |||
- apt-get update && apt-get install -y locales | |||
- echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen | |||
- locale-gen en_US.UTF-8 | |||
run_command: /lib/systemd/systemd | |||
verifier: | |||
# https://www.inspec.io/ | |||
name: inspec | |||
sudo: true | |||
# cli, documentation, html, progress, json, json-min, json-rspec, junit | |||
reporter: | |||
- progress | |||
- cli | |||
inspec_tests: | |||
- path: test/integration/default | |||
suites: | |||
- name: ufw | |||
- name: default |
@@ -0,0 +1,68 @@ | |||
control 'UFW configuration' do | |||
title 'Test UFW configuration' | |||
describe directory('/etc/ufw') do | |||
it { should exist } | |||
end | |||
describe file('/etc/ufw/ufw.conf') do | |||
its('content') { should include 'ENABLED=' } | |||
its('content') { should include 'LOGLEVEL=' } | |||
end | |||
describe command('ufw status verbose | grep Status') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /active/ } | |||
end | |||
describe command('ufw status verbose | grep Logging') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /low/ } | |||
end | |||
describe command('ufw status | grep MySQL') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /ALLOW/ } | |||
end | |||
describe command('ufw status | grep Postgresql') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /LIMIT/ } | |||
end | |||
describe command('ufw status | grep SSH223') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end | |||
describe command('ufw status | grep 10.0.0.0') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end | |||
describe command('ufw status | grep 22/tcp') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /LIMIT/ } | |||
end | |||
describe command('ufw status | grep 80/tcp') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end | |||
describe command('ufw status | grep 443/tcp') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /ALLOW/ } | |||
end | |||
describe command('ufw status | grep 10.0.0.1') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end | |||
describe command('ufw status | grep 10.0.0.2') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end | |||
end |
@@ -0,0 +1,7 @@ | |||
control 'UFW package' do | |||
title 'should be installed' | |||
describe package('ufw') do | |||
it { should be_installed } | |||
end | |||
end |
@@ -0,0 +1,12 @@ | |||
name: ufw | |||
title: UFW Formula | |||
maintainer: Alexandre Anriot | |||
license: Apache-2.0 | |||
summary: Verify that the ufw formula is setup and configured correctly | |||
supports: | |||
- os-name: debian | |||
- os-name: ubuntu | |||
- os-name: centos | |||
- os-name: fedora | |||
- os-name: opensuse | |||
- os-name: suse |
@@ -1,71 +0,0 @@ | |||
# encoding: utf-8 | |||
title 'Test Ufw installation' | |||
describe package('ufw') do | |||
it { should be_installed } | |||
end | |||
describe directory('/etc/ufw') do | |||
it { should exist } | |||
end | |||
describe file('/etc/ufw/ufw.conf') do | |||
its('content') { should include 'ENABLED=' } | |||
its('content') { should include 'LOGLEVEL=' } | |||
end | |||
describe command('ufw status verbose | grep Status') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /active/ } | |||
end | |||
describe command('ufw status verbose | grep Logging') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /low/ } | |||
end | |||
describe command('ufw status | grep MySQL') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /ALLOW/ } | |||
end | |||
describe command('ufw status | grep Postgresql') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /LIMIT/ } | |||
end | |||
describe command('ufw status | grep SSH223') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end | |||
describe command('ufw status | grep 10.0.0.0') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end | |||
describe command('ufw status | grep 22/tcp') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /LIMIT/ } | |||
end | |||
describe command('ufw status | grep 80/tcp') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end | |||
describe command('ufw status | grep 443/tcp') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /ALLOW/ } | |||
end | |||
describe command('ufw status | grep 10.0.0.1') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end | |||
describe command('ufw status | grep 10.0.0.2') do | |||
its('exit_status') { should eq 0 } | |||
its('stdout') { should match /DENY/ } | |||
end |
@@ -1,10 +0,0 @@ | |||
name: ufw | |||
title: Ufw Profile | |||
maintainer: Alexandre Anriot | |||
copyright: Alexandre Anriot | |||
copyright_email: alexandre@atlantilde.com | |||
license: MIT | |||
summary: Ufw Compliance Profile | |||
version: 0.1.0 | |||
supports: | |||
- os-family: linux |
@@ -0,0 +1,51 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- set sls_package_install = tplroot ~ '.package.install' %} | |||
{%- set sls_enable_service = tplroot ~ '.service.enable' %} | |||
{%- set sls_reload_service = tplroot ~ '.service.reload' %} | |||
{%- from tplroot ~ "/map.jinja" import ufw with context %} | |||
include: | |||
- {{ sls_package_install }} | |||
- {{ sls_enable_service }} | |||
- {{ sls_reload_service }} | |||
# Applications | |||
{%- for app_name, app_details in ufw.get('applications', {}).items() %} | |||
{%- set from_addr_raw = app_details.get('from_addr', [None]) %} | |||
{%- set from_addrs = [from_addr_raw] if from_addr_raw is string else from_addr_raw %} | |||
{%- for from_addr in from_addrs %} | |||
{%- set deny = app_details.get('deny', None) %} | |||
{%- set limit = app_details.get('limit', None) %} | |||
{%- set method = 'deny' if deny else ('limit' if limit else 'allow') %} | |||
{%- set to_addr = app_details.get('to_addr', None) %} | |||
{%- set comment = app_details.get('comment', None) %} | |||
{%- if from_addr is not none %} | |||
ufw-app-{{method}}-{{app_name}}-{{from_addr}}: | |||
{%- else %} | |||
ufw-app-{{method}}-{{app_name}}: | |||
{%- endif %} | |||
ufw.{{method}}: | |||
- app: '"{{app_name}}"' | |||
{%- if from_addr is not none %} | |||
- from_addr: {{from_addr}} | |||
{%- endif %} | |||
{%- if to_addr is not none %} | |||
- to_addr: {{to_addr}} | |||
{%- endif %} | |||
# Debian Jessie doesn't implement the **comment** directive | |||
# CentOS-6 throws an UTF-8 error | |||
{%- if comment is not none and salt['grains.get']('osfinger') != 'Debian-8' and salt['grains.get']('osfinger') != 'CentOS-6' %} | |||
- comment: '"{{comment}}"' | |||
{%- endif %} | |||
- listen_in: | |||
- cmd: reload-ufw | |||
{%- endfor %} | |||
{%- endfor %} |
@@ -0,0 +1,49 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- set sls_package_install = tplroot ~ '.package.install' %} | |||
{%- from tplroot ~ "/map.jinja" import ufw with context %} | |||
{%- from tplroot ~ "/libtofs.jinja" import files_switch with context %} | |||
include: | |||
- {{ sls_package_install }} | |||
ufw-default-file-file-managed: | |||
file.managed: | |||
- name: {{ ufw.default_file }} | |||
- user: root | |||
- group: root | |||
- template: jinja | |||
- source: {{ files_switch(['ufw.default.tmpl', 'ufw.default.tmpl.jinja'], | |||
lookup='ufw-default-file-file-managed' | |||
) | |||
}} | |||
- require: | |||
- sls: {{ sls_package_install }} | |||
- context: | |||
ufw_settings: {{ ufw.settings | json }} | |||
ufw-sysctl-file-file-managed: | |||
file.managed: | |||
- name: {{ ufw.sysctl_file }} | |||
- user: root | |||
- group: root | |||
- template: jinja | |||
- source: {{ files_switch(['ufw.sysctl.tmpl', 'ufw.sysctl.tmpl.jinja'], | |||
lookup='ufw-sysctl-file-file-managed' | |||
) | |||
}} | |||
- require: | |||
- sls: {{ sls_package_install }} | |||
- context: | |||
ufw_sysctl: {{ ufw.sysctl | json }} | |||
/etc/ufw/applications.d: | |||
file.recurse: | |||
- user: root | |||
- group: root | |||
- file_mode: 644 | |||
- clean: False | |||
- source: salt://ufw/files/applications.d |
@@ -0,0 +1,9 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
include: | |||
- .file | |||
- .services | |||
- .applications | |||
- .interfaces | |||
- .open |
@@ -0,0 +1,29 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- set sls_package_install = tplroot ~ '.package.install' %} | |||
{%- set sls_enable_service = tplroot ~ '.service.enable' %} | |||
{%- set sls_reload_service = tplroot ~ '.service.reload' %} | |||
{%- from tplroot ~ "/map.jinja" import ufw with context %} | |||
include: | |||
- {{ sls_package_install }} | |||
- {{ sls_enable_service }} | |||
- {{ sls_reload_service }} | |||
# Interfaces | |||
{%- for interface_name, interface_details in ufw.get('interfaces', {}).items() %} | |||
{%- set comment = interface_details.get('comment', None) %} | |||
ufw-interface-{{interface_name}}: | |||
ufw.allowed: | |||
- interface: {{interface_name}} | |||
{%- if comment is not none %} | |||
- comment: '"{{comment}}"' | |||
{%- endif %} | |||
- listen_in: | |||
- cmd: reload-ufw | |||
{%- endfor %} |
@@ -0,0 +1,29 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- set sls_package_install = tplroot ~ '.package.install' %} | |||
{%- set sls_enable_service = tplroot ~ '.service.enable' %} | |||
{%- set sls_reload_service = tplroot ~ '.service.reload' %} | |||
{%- from tplroot ~ "/map.jinja" import ufw with context %} | |||
include: | |||
- {{ sls_package_install }} | |||
- {{ sls_enable_service }} | |||
- {{ sls_reload_service }} | |||
# Open | |||
{%- for open_addr, open_details in ufw.get('open', {}).items() %} | |||
{%- set comment = open_details.get('comment', None) %} | |||
ufw-open-{{open_addr}}: | |||
ufw.allowed: | |||
- from_addr: {{open_addr}} | |||
{%- if comment is not none %} | |||
- comment: '"{{comment}}"' | |||
{%- endif %} | |||
- listen_in: | |||
- cmd: reload-ufw | |||
{%- endfor %} |
@@ -0,0 +1,56 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- set sls_package_install = tplroot ~ '.package.install' %} | |||
{%- set sls_enable_service = tplroot ~ '.service.enable' %} | |||
{%- set sls_reload_service = tplroot ~ '.service.reload' %} | |||
{%- from tplroot ~ "/map.jinja" import ufw with context %} | |||
include: | |||
- {{ sls_package_install }} | |||
- {{ sls_enable_service }} | |||
- {{ sls_reload_service }} | |||
# Services | |||
{%- for service_name, service_details in ufw.get('services', {}).items() %} | |||
{%- set from_addr_raw = service_details.get('from_addr', [None]) %} | |||
{%- set from_addrs = [from_addr_raw] if from_addr_raw is string else from_addr_raw %} | |||
{%- for from_addr in from_addrs %} | |||
{%- set protocol = service_details.get('protocol', None) %} | |||
{%- set deny = service_details.get('deny', None) %} | |||
{%- set limit = service_details.get('limit', None) %} | |||
{%- set method = 'deny' if deny else ('limit' if limit else 'allow') %} | |||
{%- set from_port = service_details.get('from_port', None) %} | |||
{%- set to_addr = service_details.get('to_addr', None) %} | |||
{%- set to_port = service_details.get('to_port', service_name) %} | |||
{%- set comment = service_details.get('comment', None) %} | |||
ufw-svc-{{method}}-{{service_name}}-{{from_addr}}: | |||
ufw.{{method}}: | |||
{%- if protocol is not none %} | |||
- protocol: {{protocol}} | |||
{%- endif %} | |||
{%- if from_addr is not none %} | |||
- from_addr: {{from_addr}} | |||
{%- endif %} | |||
{%- if from_port is not none %} | |||
- from_port: "{{from_port}}" | |||
{%- endif %} | |||
{%- if to_addr is not none %} | |||
- to_addr: {{to_addr}} | |||
{%- endif %} | |||
# Debian Jessie doesn't implement the **comment** directive | |||
# CentOS-6 throws an UTF-8 error | |||
{%- if comment is not none and salt['grains.get']('osfinger') != 'Debian-8' and salt['grains.get']('osfinger') != 'CentOS-6' %} | |||
- comment: '"{{comment}}"' | |||
{%- endif %} | |||
- to_port: "{{to_port}}" | |||
- listen_in: | |||
- cmd: reload-ufw | |||
{%- endfor %} | |||
{%- endfor %} |
@@ -1,2 +1,17 @@ | |||
ufwmap: | |||
pkg: ufw | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=yaml | |||
--- | |||
ufw: | |||
package: ufw | |||
packages: [] | |||
service: | |||
name: ufw | |||
default_file: /etc/default/ufw | |||
sysctl_file: /etc/ufw/sysctl.conf | |||
enabled: false | |||
settings: {} | |||
sysctl: {} | |||
services: {} | |||
applications: {} | |||
interfaces: {} | |||
open: {} |
@@ -12,7 +12,3 @@ ports=3306/tcp | |||
title=Postgresql database server | |||
description=Postgresql database server. | |||
ports=5432/tcp | |||
@@ -1,17 +1,15 @@ | |||
{% set ufw_cfg = pillar.get('ufw', {}) -%} | |||
{% set settings_cfg = ufw_cfg.get('settings', {}) -%} | |||
{% set ipv6 = "yes" if settings_cfg.get('ipv6', True) else "no" -%} | |||
{% set default_input_policy = settings_cfg.get('default_input_policy', 'DROP') -%} | |||
{% set default_output_policy = settings_cfg.get('default_output_policy', 'ACCEPT') -%} | |||
{% set default_forward_policy = settings_cfg.get('default_forward_policy', 'DROP') -%} | |||
{% set default_application_policy = settings_cfg.get('default_application_policy', 'SKIP') -%} | |||
{% set manage_builtins = "yes" if settings_cfg.get('manage_builtins', False) else "no" -%} | |||
{% set ipt_sysctl = settings_cfg.get('ipt_sysctl', '/etc/ufw/sysctl.conf') -%} | |||
{% set ipt_modules = settings_cfg.get('ipt_modules', ['nf_conntrack_ftp', 'nf_nat_ftp', 'nf_conntrack_netbios_ns'])|join(" ") -%} | |||
# /etc/default/ufw | |||
# | |||
# File managed by Salt. Do not edit manually. | |||
######################################################################## | |||
# File managed by Salt at <{{ source }}>. | |||
# Your changes will be overwritten. | |||
######################################################################## | |||
{%- set ipv6 = "yes" if ufw_settings.get('ipv6', True) else "no" %} | |||
{%- set default_input_policy = ufw_settings.get('default_input_policy', 'DROP') %} | |||
{%- set default_output_policy = ufw_settings.get('default_output_policy', 'ACCEPT') %} | |||
{%- set default_forward_policy = ufw_settings.get('default_forward_policy', 'DROP') %} | |||
{%- set default_application_policy = ufw_settings.get('default_application_policy', 'SKIP') %} | |||
{%- set manage_builtins = "yes" if ufw_settings.get('manage_builtins', False) else "no" %} | |||
{%- set ipt_sysctl = ufw_settings.get('ipt_sysctl', '/etc/ufw/sysctl.conf') %} | |||
{%- set ipt_modules = ufw_settings.get('ipt_modules', ['nf_conntrack_ftp', 'nf_nat_ftp', 'nf_conntrack_netbios_ns'])|join(" ") %} | |||
# Set to yes to apply rules to support IPv6 (no means only IPv6 on loopback | |||
# accepted). You will need to 'disable' and then 'enable' the firewall for |
@@ -1,23 +1,23 @@ | |||
{% set ufw_cfg = pillar.get('ufw', {}) -%} | |||
{% set sysctl_cfg = ufw_cfg.get('sysctl', {}) -%} | |||
{% set forwarding = sysctl_cfg.get('forwarding', 0) -%} | |||
{% set rp_filter = sysctl_cfg.get('rp_filter', 1) -%} | |||
{% set accept_source_route = sysctl_cfg.get('accept_source_route', 0) -%} | |||
{% set accept_redirects = sysctl_cfg.get('accept_redirects', 0) -%} | |||
{% set icmp_echo_ignore_broadcasts = sysctl_cfg.get('icmp_echo_ignore_broadcasts', 1) -%} | |||
{% set icmp_ignore_bogus_error_responses = sysctl_cfg.get('icmp_ignore_bogus_error_responses', 1) -%} | |||
{% set icmp_echo_ignore_all = sysctl_cfg.get('icmp_echo_ignore_all', 0) -%} | |||
{% set log_martians = sysctl_cfg.get('log_martians', 0) -%} | |||
{% set tcp_syncookies = sysctl_cfg.get('tcp_syncookies', 0) -%} | |||
{% set tcp_sack = sysctl_cfg.get('tcp_sack', 1) -%} | |||
{% set ipv6_autoconf = sysctl_cfg.get('ipv6_autoconf', 1) -%} | |||
{% set use_tempaddr = sysctl_cfg.get('use_tempaddr', 1) -%} | |||
# File managed by Salt. Do not edit manually. | |||
# | |||
######################################################################## | |||
# File managed by Salt at <{{ source }}>. | |||
# Your changes will be overwritten. | |||
######################################################################## | |||
{%- set forwarding = ufw_sysctl.get('forwarding', 0) %} | |||
{%- set rp_filter = ufw_sysctl.get('rp_filter', 1) %} | |||
{%- set accept_source_route = ufw_sysctl.get('accept_source_route', 0) %} | |||
{%- set accept_redirects = ufw_sysctl.get('accept_redirects', 0) %} | |||
{%- set icmp_echo_ignore_broadcasts = ufw_sysctl.get('icmp_echo_ignore_broadcasts', 1) %} | |||
{%- set icmp_ignore_bogus_error_responses = ufw_sysctl.get('icmp_ignore_bogus_error_responses', 1) %} | |||
{%- set icmp_echo_ignore_all = ufw_sysctl.get('icmp_echo_ignore_all', 0) %} | |||
{%- set log_martians = ufw_sysctl.get('log_martians', 0) %} | |||
{%- set tcp_syncookies = ufw_sysctl.get('tcp_syncookies', 0) %} | |||
{%- set tcp_sack = ufw_sysctl.get('tcp_sack', 1) %} | |||
{%- set ipv6_autoconf = ufw_sysctl.get('ipv6_autoconf', 1) %} | |||
{%- set use_tempaddr = ufw_sysctl.get('use_tempaddr', 1) %} | |||
# Configuration file for setting network variables. Please note these settings | |||
# override /etc/sysctl.conf. If you prefer to use /etc/sysctl.conf, please | |||
# adjust IPT_SYSCTL in /etc/default/ufw. | |||
# | |||
# Uncomment this to allow this host to route packets between interfaces | |||
net/ipv4/ip_forward={{ forwarding }} | |||
@@ -69,4 +69,4 @@ net/ipv6/conf/all/autoconf={{ ipv6_autoconf }} | |||
# Uncomment this to enable ipv6 privacy addressing | |||
net/ipv6/conf/default/use_tempaddr={{ use_tempaddr }} | |||
net/ipv6/conf/all/use_tempaddr={{ use_tempaddr }} | |||
net/ipv6/conf/all/use_tempaddr={{ use_tempaddr }} |
@@ -1,175 +1,7 @@ | |||
# UFW management module | |||
{%- set ufw = pillar.get('ufw', {}) %} | |||
{%- if ufw.get('enabled', False) %} | |||
{% from "ufw/map.jinja" import ufwmap with context %} | |||
{% set default_template = ufw.get('default_template', 'salt://ufw/templates/default.jinja') -%} | |||
{% set sysctl_template = ufw.get('sysctl_template', 'salt://ufw/templates/sysctl.jinja') -%} | |||
{% set settings_cfg = ufw.get('settings', {}) -%} | |||
{% set loglevel = settings_cfg.get('loglevel', 'low') -%} | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
ufw: | |||
pkg.installed: | |||
- name: {{ ufwmap.pkg }} | |||
service.running: | |||
- enable: True | |||
- watch: | |||
- file: /etc/default/ufw | |||
- file: /etc/ufw/sysctl.conf | |||
/etc/default/ufw: | |||
file.managed: | |||
- template: jinja | |||
- user: root | |||
- group: root | |||
- mode: 644 | |||
- source: {{ default_template }} | |||
/etc/ufw/sysctl.conf: | |||
file.managed: | |||
- template: jinja | |||
- user: root | |||
- group: root | |||
- mode: 644 | |||
- source: {{ sysctl_template }} | |||
/etc/ufw/applications.d: | |||
file.recurse: | |||
- user: root | |||
- group: root | |||
- file_mode: 644 | |||
- clean: False | |||
- source: salt://ufw/files/applications.d | |||
# services | |||
{%- for service_name, service_details in ufw.get('services', {}).items() %} | |||
{%- set from_addr_raw = service_details.get('from_addr', [None]) -%} | |||
{%- set from_addrs = [from_addr_raw] if from_addr_raw is string else from_addr_raw -%} | |||
{%- for from_addr in from_addrs %} | |||
{%- set protocol = service_details.get('protocol', None) %} | |||
{%- set deny = service_details.get('deny', None) %} | |||
{%- set limit = service_details.get('limit', None) %} | |||
{%- set method = 'deny' if deny else ('limit' if limit else 'allow') -%} | |||
{%- set from_port = service_details.get('from_port', None) %} | |||
{%- set to_addr = service_details.get('to_addr', None) %} | |||
{%- set to_port = service_details.get('to_port', service_name) %} | |||
{%- set comment = service_details.get('comment', None) %} | |||
ufw-svc-{{method}}-{{service_name}}-{{from_addr}}: | |||
ufw.{{method}}: | |||
{%- if protocol != None %} | |||
- protocol: {{protocol}} | |||
{%- endif %} | |||
{%- 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 %} | |||
{%- if comment != None %} | |||
- comment: '"{{comment}}"' | |||
{%- endif %} | |||
- to_port: "{{to_port}}" | |||
- require: | |||
- pkg: ufw | |||
- listen_in: | |||
- cmd: reload-ufw | |||
{%- endfor %} | |||
{%- endfor %} | |||
# Applications | |||
{%- for app_name, app_details in ufw.get('applications', {}).items() %} | |||
{%- set from_addr_raw = app_details.get('from_addr', [None]) -%} | |||
{%- set from_addrs = [from_addr_raw] if from_addr_raw is string else from_addr_raw -%} | |||
{%- for from_addr in from_addrs %} | |||
{%- set deny = app_details.get('deny', None) %} | |||
{%- set limit = app_details.get('limit', None) %} | |||
{%- set method = 'deny' if deny else ('limit' if limit else 'allow') -%} | |||
{%- set to_addr = app_details.get('to_addr', None) %} | |||
{%- set comment = app_details.get('comment', None) %} | |||
{%- if from_addr != None%} | |||
ufw-app-{{method}}-{{app_name}}-{{from_addr}}: | |||
{%- else %} | |||
ufw-app-{{method}}-{{app_name}}: | |||
{%- endif %} | |||
ufw.{{method}}: | |||
- app: '"{{app_name}}"' | |||
{%- if from_addr != None %} | |||
- from_addr: {{from_addr}} | |||
{%- endif %} | |||
{%- if to_addr != None %} | |||
- to_addr: {{to_addr}} | |||
{%- endif %} | |||
{%- if comment != None %} | |||
- comment: '"{{comment}}"' | |||
{%- endif %} | |||
- require: | |||
- pkg: ufw | |||
- listen_in: | |||
- cmd: reload-ufw | |||
{%- endfor %} | |||
{%- endfor %} | |||
# Interfaces | |||
{%- for interface_name, interface_details in ufw.get('interfaces', {}).items() %} | |||
{%- set comment = interface_details.get('comment', None) %} | |||
ufw-interface-{{interface_name}}: | |||
ufw.allowed: | |||
- interface: {{interface_name}} | |||
{%- if comment != None %} | |||
- comment: '"{{comment}}"' | |||
{%- endif %} | |||
- require: | |||
- pkg: ufw | |||
- listen_in: | |||
- cmd: reload-ufw | |||
{%- endfor %} | |||
# Open | |||
{%- for open_addr, open_details in ufw.get('open', {}).items() %} | |||
{%- set comment = open_details.get('comment', None) %} | |||
ufw-open-{{open_addr}}: | |||
ufw.allowed: | |||
- from_addr: {{open_addr}} | |||
{%- if comment != None %} | |||
- comment: '"{{comment}}"' | |||
{%- endif %} | |||
- require: | |||
- pkg: ufw | |||
- listen_in: | |||
- cmd: reload-ufw | |||
{%- endfor %} | |||
enable-ufw: | |||
ufw.enabled: | |||
- require: | |||
- pkg: ufw | |||
reload-ufw: | |||
cmd.wait: | |||
- name: ufw reload | |||
set-logging: | |||
cmd.run: | |||
- name: ufw logging {{ loglevel }} | |||
- unless: "grep 'LOGLEVEL={{ loglevel }}' /etc/ufw/ufw.conf" | |||
{% else %} | |||
#ufw: | |||
#ufw: | |||
#- disabled | |||
{% endif %} | |||
include: | |||
- .package | |||
- .config | |||
- .service |
@@ -0,0 +1,100 @@ | |||
{%- macro files_switch(source_files, | |||
lookup=None, | |||
default_files_switch=['id', 'os_family'], | |||
indent_width=6, | |||
v1_path_prefix='') %} | |||
{#- | |||
Returns a valid value for the "source" parameter of a "file.managed" | |||
state function. This makes easier the usage of the Template Override and | |||
Files Switch (TOFS) pattern. | |||
Params: | |||
* source_files: ordered list of files to look for | |||
* lookup: key under '<tplroot>:tofs:source_files' to override | |||
list of source files | |||
* default_files_switch: if there's no config (e.g. pillar) | |||
'<tplroot>:tofs:files_switch' this is the ordered list of grains to | |||
use as selector switch of the directories under | |||
"<path_prefix>/files" | |||
* indent_witdh: indentation of the result value to conform to YAML | |||
* v1_path_prefix: (deprecated) only used for injecting a path prefix into | |||
the source, to support older TOFS configs | |||
Example (based on a `tplroot` of `xxx`): | |||
If we have a state: | |||
Deploy configuration: | |||
file.managed: | |||
- name: /etc/yyy/zzz.conf | |||
- source: {{ files_switch(['/etc/yyy/zzz.conf', '/etc/yyy/zzz.conf.jinja'], | |||
lookup='Deploy configuration' | |||
) }} | |||
- template: jinja | |||
In a minion with id=theminion and os_family=RedHat, it's going to be | |||
rendered as: | |||
Deploy configuration: | |||
file.managed: | |||
- name: /etc/yyy/zzz.conf | |||
- source: | |||
- salt://xxx/files/theminion/etc/yyy/zzz.conf | |||
- salt://xxx/files/theminion/etc/yyy/zzz.conf.jinja | |||
- salt://xxx/files/RedHat/etc/yyy/zzz.conf | |||
- salt://xxx/files/RedHat/etc/yyy/zzz.conf.jinja | |||
- salt://xxx/files/default/etc/yyy/zzz.conf | |||
- salt://xxx/files/default/etc/yyy/zzz.conf.jinja | |||
- template: jinja | |||
#} | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- set path_prefix = salt['config.get'](tplroot ~ ':tofs:path_prefix', tplroot) %} | |||
{%- set files_dir = salt['config.get'](tplroot ~ ':tofs:dirs:files', 'files') %} | |||
{%- set files_switch_list = salt['config.get']( | |||
tplroot ~ ':tofs:files_switch', | |||
default_files_switch | |||
) %} | |||
{#- Lookup source_files (v2), files (v1), or fallback to source_files parameter #} | |||
{%- set src_files = salt['config.get']( | |||
tplroot ~ ':tofs:source_files:' ~ lookup, | |||
salt['config.get']( | |||
tplroot ~ ':tofs:files:' ~ lookup, | |||
source_files | |||
) | |||
) %} | |||
{#- Only add to [''] when supporting older TOFS implementations #} | |||
{%- set path_prefix_exts = [''] %} | |||
{%- if v1_path_prefix != '' %} | |||
{%- do path_prefix_exts.append(v1_path_prefix) %} | |||
{%- endif %} | |||
{%- for path_prefix_ext in path_prefix_exts %} | |||
{%- set path_prefix_inc_ext = path_prefix ~ path_prefix_ext %} | |||
{#- For older TOFS implementation, use `files_switch` from the config #} | |||
{#- Use the default, new method otherwise #} | |||
{%- set fsl = salt['config.get']( | |||
tplroot ~ path_prefix_ext|replace('/', ':') ~ ':files_switch', | |||
files_switch_list | |||
) %} | |||
{#- Append an empty value to evaluate as `default` in the loop below #} | |||
{%- if '' not in fsl %} | |||
{%- do fsl.append('') %} | |||
{%- endif %} | |||
{%- for fs in fsl %} | |||
{%- for src_file in src_files %} | |||
{%- if fs %} | |||
{%- set fs_dir = salt['config.get'](fs, fs) %} | |||
{%- else %} | |||
{%- set fs_dir = salt['config.get'](tplroot ~ ':tofs:dirs:default', 'default') %} | |||
{%- endif %} | |||
{%- set url = '- salt://' ~ '/'.join([ | |||
path_prefix_inc_ext, | |||
files_dir, | |||
fs_dir, | |||
src_file.lstrip('/') | |||
]) %} | |||
{{ url | indent(indent_width, true) }} | |||
{%- endfor %} | |||
{%- endfor %} | |||
{%- endfor %} | |||
{%- endmacro %} |
@@ -1,17 +1,24 @@ | |||
{% import_yaml 'ufw/defaults.yaml' as default_settings %} | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=jinja | |||
{% set os_family_map = salt['grains.filter_by']({ | |||
'Gentoo': { | |||
'pkg': 'net-firewall/ufw', | |||
}, | |||
}, | |||
grain="os_family", | |||
merge=salt['pillar.get']('ufw:lookup')) or {} | |||
%} | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{#- Start imports as #} | |||
{%- import_yaml tplroot ~ "/defaults.yaml" or {} as default_settings %} | |||
{%- import_yaml tplroot ~ "/osfamilymap.yaml" or {} as osfamilymap %} | |||
{%- import_yaml tplroot ~ "/osmap.yaml" or {} as osmap %} | |||
{%- import_yaml tplroot ~ "/osfingermap.yaml" or {} as osfingermap %} | |||
{% set ufwmap = salt['grains.filter_by']( | |||
default_settings, | |||
merge=os_family_map, | |||
base='ufwmap', | |||
{%- set defaults = salt['grains.filter_by'](default_settings, | |||
default='ufw', | |||
merge=salt['grains.filter_by'](osfamilymap, grain='os_family', | |||
merge=salt['grains.filter_by'](osmap, grain='os', | |||
merge=salt['grains.filter_by'](osfingermap, grain='osfinger', | |||
merge=salt['pillar.get']('ufw:lookup', default={}) | |||
) | |||
) | |||
%} | |||
) | |||
) %} | |||
{#- Merge the ufw pillar #} | |||
{%- set ufw = salt['pillar.get']('ufw', default=defaults, merge=True) %} |
@@ -0,0 +1,12 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=yaml | |||
--- | |||
Debian: | |||
packages: | |||
- python-ufw | |||
RedHat: {} | |||
Suse: | |||
packages: | |||
- iptables | |||
Gentoo: | |||
package: net-firewall/ufw |
@@ -0,0 +1,12 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=yaml | |||
--- | |||
Debian-8: {} | |||
Debian-9: {} | |||
Ubuntu-16.04: {} | |||
Ubuntu-18.04: {} | |||
Fedora-28: {} | |||
Fedora-29: {} | |||
CentOS-7: {} | |||
CentOS-6: {} | |||
openSUSE-4.23: {} |
@@ -0,0 +1,8 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=yaml | |||
--- | |||
Debian: {} | |||
Ubuntu: {} | |||
Fedora: {} | |||
CentOS: {} | |||
openSUSE: {} |
@@ -0,0 +1,5 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
include: | |||
- .install |
@@ -0,0 +1,16 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- from tplroot ~ "/map.jinja" import ufw with context %} | |||
ufw-package-install-pkg-installed: | |||
pkg.installed: | |||
- name: {{ ufw.package }} | |||
{%- for pkg in ufw.packages %} | |||
ufw-package-{{ pkg }}-install-pkg-installed: | |||
pkg.installed: | |||
- name: {{ pkg }} | |||
{%- endfor %} |
@@ -1,3 +0,0 @@ | |||
python-ufw: | |||
pkg.installed: | |||
- name: python-ufw |
@@ -0,0 +1,18 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- from tplroot ~ "/map.jinja" import ufw with context %} | |||
{%- if ufw.get('enabled', False) %} | |||
{%- set loglevel = ufw.get('settings:loglevel', 'low') %} | |||
enable-ufw: | |||
ufw.enabled | |||
set-logging: | |||
cmd.run: | |||
- name: ufw logging {{ loglevel }} | |||
- unless: "grep 'LOGLEVEL={{ loglevel }}' /etc/ufw/ufw.conf" | |||
{%- endif %} |
@@ -0,0 +1,6 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
include: | |||
- .enable | |||
- .running |
@@ -0,0 +1,14 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- from tplroot ~ "/map.jinja" import ufw with context %} | |||
{%- if ufw.get('enabled', False) %} | |||
reload-ufw: | |||
cmd.wait: | |||
- name: ufw reload | |||
{%- endif %} |
@@ -0,0 +1,30 @@ | |||
# -*- coding: utf-8 -*- | |||
# vim: ft=sls | |||
{#- Get the `tplroot` from `tpldir` #} | |||
{%- set tplroot = tpldir.split('/')[0] %} | |||
{%- set sls_config_file = tplroot ~ '.config.file' %} | |||
{%- from tplroot ~ "/map.jinja" import ufw with context %} | |||
include: | |||
- {{ sls_config_file }} | |||
{%- if ufw.get('enabled', False) %} | |||
ufw-service-running-service-running: | |||
service.running: | |||
- name: {{ ufw.service.name }} | |||
- enable: true | |||
- require: | |||
- sls: {{ sls_config_file }} | |||
{%- else %} | |||
ufw-service-dead-service-dead: | |||
service.dead: | |||
- name: {{ ufw.service.name }} | |||
- enable: false | |||
- require: | |||
- sls: {{ sls_config_file }} | |||
{%- endif %} |