From c9141785fd50f34bde5eb6fc474223eac5768f37 Mon Sep 17 00:00:00 2001 From: Alex Vandiver Date: Tue, 25 May 2021 02:12:28 +0000 Subject: [PATCH] puppet: Use concat fragments to place port allows next to services. This means that services will only open their ports if they are actually run, without having to clutter rules.v4 with a log of `if` statements. This does not go as far as using `puppetlabs/firewall`[1] because that would represent an additional DSL to learn; raw IPtables sections can easily be inserted into the generated iptables file via `concat::fragment` (either inline, or as a separate file), but config can be centralized next to the appropriate service. [1] https://forge.puppet.com/modules/puppetlabs/firewall --- puppet/deps.yaml | 1 + puppet/zulip_ops/files/iptables/header | 21 +++++++ puppet/zulip_ops/files/iptables/trailer | 6 ++ puppet/zulip_ops/files/iptables/zmirror | 9 +++ puppet/zulip_ops/manifests/app_frontend.pp | 4 ++ puppet/zulip_ops/manifests/camo.pp | 2 + puppet/zulip_ops/manifests/firewall.pp | 18 ++++-- puppet/zulip_ops/manifests/firewall_allow.pp | 21 +++++++ puppet/zulip_ops/manifests/profile/base.pp | 2 + puppet/zulip_ops/manifests/profile/nagios.pp | 2 + .../zulip_ops/manifests/profile/postgresql.pp | 2 + .../manifests/profile/smokescreen.pp | 3 + puppet/zulip_ops/manifests/profile/zmirror.pp | 7 +++ .../manifests/profile/zmirror_personals.pp | 7 +++ .../zulip_ops/templates/iptables/rules.v4.erb | 59 ------------------- 15 files changed, 101 insertions(+), 63 deletions(-) create mode 100644 puppet/zulip_ops/files/iptables/header create mode 100644 puppet/zulip_ops/files/iptables/trailer create mode 100644 puppet/zulip_ops/files/iptables/zmirror create mode 100644 puppet/zulip_ops/manifests/firewall_allow.pp delete mode 100644 puppet/zulip_ops/templates/iptables/rules.v4.erb diff --git a/puppet/deps.yaml b/puppet/deps.yaml index 0723418c4d..18ed154fab 100644 --- a/puppet/deps.yaml +++ b/puppet/deps.yaml @@ -1 +1,2 @@ puppetlabs-stdlib: 7.1.0 +puppetlabs-concat: 7.0.1 diff --git a/puppet/zulip_ops/files/iptables/header b/puppet/zulip_ops/files/iptables/header new file mode 100644 index 0000000000..baafc0176b --- /dev/null +++ b/puppet/zulip_ops/files/iptables/header @@ -0,0 +1,21 @@ +# This file was auto-generated by Puppet. Do not edit by hand. +*filter + +# Set up logging for dropped packets +-N LOGDROP +-A LOGDROP -m limit --limit 15/min -j LOG --log-prefix "iptables dropped: " --log-level 7 +-A LOGDROP -j DROP + +# Allow all outbound traffic +-A OUTPUT -j ACCEPT + +# Accept all loopback traffic +-A INPUT -i lo -j ACCEPT + +# Drop all traffic to loopback IPs on other interfaces +-A INPUT ! -i lo -d 127.0.0.0/8 -j LOGDROP + +# Accept incoming traffic related to established connections +-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT + +# Host-specific rules follow: diff --git a/puppet/zulip_ops/files/iptables/trailer b/puppet/zulip_ops/files/iptables/trailer new file mode 100644 index 0000000000..e714d62bf2 --- /dev/null +++ b/puppet/zulip_ops/files/iptables/trailer @@ -0,0 +1,6 @@ + +# Drop everything else +-A INPUT -j LOGDROP +-A FORWARD -j LOGDROP + +COMMIT diff --git a/puppet/zulip_ops/files/iptables/zmirror b/puppet/zulip_ops/files/iptables/zmirror new file mode 100644 index 0000000000..c0a216a695 --- /dev/null +++ b/puppet/zulip_ops/files/iptables/zmirror @@ -0,0 +1,9 @@ +# Accept incoming traffic on UDP port 2104 (zhm) +-A INPUT -p udp --dport 2104 -j ACCEPT + +# It's hard to know what ephemeral ports the zephyr clients are listening on. +# Apparently they do not send outgoing traffic sufficient for the +# ESTABLISHED,RELATED rule above. So for now we allow all UDP traffic. +# +# FIXME: do something better here. +-A INPUT -p udp -j ACCEPT diff --git a/puppet/zulip_ops/manifests/app_frontend.pp b/puppet/zulip_ops/manifests/app_frontend.pp index 138342a1f6..194c28ce53 100644 --- a/puppet/zulip_ops/manifests/app_frontend.pp +++ b/puppet/zulip_ops/manifests/app_frontend.pp @@ -11,6 +11,10 @@ class zulip_ops::app_frontend { package { $app_packages: ensure => 'installed' } $redis_hostname = zulipconf('redis', 'hostname', undef) + zulip_ops::firewall_allow{ 'smtp': } + zulip_ops::firewall_allow{ 'http': } + zulip_ops::firewall_allow{ 'https': } + file { '/etc/logrotate.d/zulip': ensure => file, owner => 'root', diff --git a/puppet/zulip_ops/manifests/camo.pp b/puppet/zulip_ops/manifests/camo.pp index 8a619f5814..5b6b2c6e4f 100644 --- a/puppet/zulip_ops/manifests/camo.pp +++ b/puppet/zulip_ops/manifests/camo.pp @@ -1,6 +1,8 @@ class zulip_ops::camo { include zulip::camo + zulip_ops::firewall_allow { 'camo': port => '9292' } + file { '/etc/cron.d/camo': ensure => file, owner => 'root', diff --git a/puppet/zulip_ops/manifests/firewall.pp b/puppet/zulip_ops/manifests/firewall.pp index 79e78ce592..2da2a503b6 100644 --- a/puppet/zulip_ops/manifests/firewall.pp +++ b/puppet/zulip_ops/manifests/firewall.pp @@ -1,11 +1,21 @@ class zulip_ops::firewall { package { 'iptables-persistent': } - file { '/etc/iptables/rules.v4': - ensure => file, + concat { '/etc/iptables/rules.v4': + ensure => present, mode => '0600', - content => template('zulip_ops/iptables/rules.v4.erb'), require => Package['iptables-persistent'], } + + concat::fragment { 'iptables-header': + target => '/etc/iptables/rules.v4', + source => 'puppet:///modules/zulip_ops/iptables/header', + order => '01', + } + concat::fragment { 'iptables-trailer': + target => '/etc/iptables/rules.v4', + source => 'puppet:///modules/zulip_ops/iptables/trailer', + order => '99', + } service { 'netfilter-persistent': ensure => running, @@ -22,6 +32,6 @@ class zulip_ops::firewall { hasrestart => false, require => Package['iptables-persistent'], - subscribe => File['/etc/iptables/rules.v4'], + subscribe => Concat['/etc/iptables/rules.v4'], } } diff --git a/puppet/zulip_ops/manifests/firewall_allow.pp b/puppet/zulip_ops/manifests/firewall_allow.pp new file mode 100644 index 0000000000..3f3079a085 --- /dev/null +++ b/puppet/zulip_ops/manifests/firewall_allow.pp @@ -0,0 +1,21 @@ +# @summary Adds an iptables "allow" rule for the host for a port. +# +# Rules with the same ordering are ordered by the rule name. +# +define zulip_ops::firewall_allow ( + $port = '', + $proto = 'tcp', + $order = '50', +) { + if $port == '' { + $portname = $name + } else { + $portname = $port + } + + concat::fragment { "iptables_${portname}": + target => '/etc/iptables/rules.v4', + order => $order, + content => "-A INPUT -p ${proto} --dport ${portname} -j ACCEPT\n", + } +} diff --git a/puppet/zulip_ops/manifests/profile/base.pp b/puppet/zulip_ops/manifests/profile/base.pp index 28660b2099..09f69c93e1 100644 --- a/puppet/zulip_ops/manifests/profile/base.pp +++ b/puppet/zulip_ops/manifests/profile/base.pp @@ -4,6 +4,8 @@ class zulip_ops::profile::base { include zulip_ops::ksplice_uptrack include zulip_ops::firewall + zulip_ops::firewall_allow { 'ssh': order => '10'} + $org_base_packages = [ # Standard kernel, not AWS', so ksplice works 'linux-image-virtual', diff --git a/puppet/zulip_ops/manifests/profile/nagios.pp b/puppet/zulip_ops/manifests/profile/nagios.pp index bd16ed0263..d4e25e3b59 100644 --- a/puppet/zulip_ops/manifests/profile/nagios.pp +++ b/puppet/zulip_ops/manifests/profile/nagios.pp @@ -58,6 +58,8 @@ class zulip_ops::profile::nagios { ], notify => Service['apache2'], } + zulip_ops::firewall_allow{ 'http': } + zulip_ops::firewall_allow{ 'https': } file { '/etc/nagios3/conf.d/contacts.cfg': require => Package[nagios3], diff --git a/puppet/zulip_ops/manifests/profile/postgresql.pp b/puppet/zulip_ops/manifests/profile/postgresql.pp index 9dbe47b6a1..6400934966 100644 --- a/puppet/zulip_ops/manifests/profile/postgresql.pp +++ b/puppet/zulip_ops/manifests/profile/postgresql.pp @@ -5,6 +5,8 @@ class zulip_ops::profile::postgresql { $common_packages = ['xfsprogs'] package { $common_packages: ensure => 'installed' } + zulip_ops::firewall_allow{ 'postgresql': } + file { '/etc/sysctl.d/40-postgresql.conf': ensure => file, owner => 'root', diff --git a/puppet/zulip_ops/manifests/profile/smokescreen.pp b/puppet/zulip_ops/manifests/profile/smokescreen.pp index 9ed4bf3062..6ed9ce3425 100644 --- a/puppet/zulip_ops/manifests/profile/smokescreen.pp +++ b/puppet/zulip_ops/manifests/profile/smokescreen.pp @@ -1,5 +1,8 @@ class zulip_ops::profile::smokescreen { include zulip_ops::profile::base + include zulip::profile::smokescreen + zulip_ops::firewall_allow { 'smokescreen': port => '4750' } + include zulip_ops::camo } diff --git a/puppet/zulip_ops/manifests/profile/zmirror.pp b/puppet/zulip_ops/manifests/profile/zmirror.pp index 7ceb1a36f0..f600a741e2 100644 --- a/puppet/zulip_ops/manifests/profile/zmirror.pp +++ b/puppet/zulip_ops/manifests/profile/zmirror.pp @@ -59,6 +59,13 @@ class zulip_ops::profile::zmirror { source => 'puppet:///modules/zulip_ops/nagios_plugins/zulip_zephyr_mirror', } + # Allow the relevant UDP ports + concat::fragment { 'iptables-zmirror': + target => '/etc/iptables/rules.v4', + source => 'puppet:///modules/zulip_ops/iptables/zmirror', + order => '20', + } + # TODO: Do the rest of our setup, which includes at least: # Building python-zephyr after cloning it from https://github.com/ebroder/python-zephyr # Putting tabbott/extra's keytab on the system at /home/zulip/tabbott.extra.keytab diff --git a/puppet/zulip_ops/manifests/profile/zmirror_personals.pp b/puppet/zulip_ops/manifests/profile/zmirror_personals.pp index 0913f1f15c..c3161844b7 100644 --- a/puppet/zulip_ops/manifests/profile/zmirror_personals.pp +++ b/puppet/zulip_ops/manifests/profile/zmirror_personals.pp @@ -49,6 +49,13 @@ class zulip_ops::profile::zmirror_personals { source => 'puppet:///modules/zulip_ops/nagios_plugins/zulip_zephyr_mirror', } + # Allow the relevant UDP ports + concat::fragment { 'iptables-zmirror': + target => '/etc/iptables/rules.v4', + source => 'puppet:///modules/zulip_ops/iptables/zmirror', + order => '20', + } + # TODO: Do the rest of our setup, which includes at least: # Building patched libzephyr4-krb5 from davidben's roost branch and installing that # (https://github.com/davidben/zephyr/commit/252258d38ebd0e79b261db336c1f74f261b77128) diff --git a/puppet/zulip_ops/templates/iptables/rules.v4.erb b/puppet/zulip_ops/templates/iptables/rules.v4.erb deleted file mode 100644 index eb93cca3de..0000000000 --- a/puppet/zulip_ops/templates/iptables/rules.v4.erb +++ /dev/null @@ -1,59 +0,0 @@ -# This file was auto-generated by Puppet. Do not edit by hand. -*filter - -# Set up logging for dropped packets --N LOGDROP --A LOGDROP -m limit --limit 15/min -j LOG --log-prefix "iptables dropped: " --log-level 7 --A LOGDROP -j DROP - -# Allow all outbound traffic --A OUTPUT -j ACCEPT - -# Accept all loopback traffic --A INPUT -i lo -j ACCEPT - -# Drop all traffic to loopback IPs on other interfaces --A INPUT ! -i lo -d 127.0.0.0/8 -j LOGDROP - -# Accept incoming traffic related to established connections --A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT - -<% if @fqdn.include? "zmirror" -%> -# Accept incoming traffic on TCP port 22 (SSH) --A INPUT -p tcp --dport 22 -j ACCEPT - -# Accept incoming traffic on UDP port 2104 (zhm) --A INPUT -p udp --dport 2104 -j ACCEPT - -# It's hard to know what ephemeral ports the zephyr clients are listening on. -# Apparently they do not send outgoing traffic sufficient for the -# ESTABLISHED,RELATED rule above. So for now we allow all UDP traffic. -# -# FIXME: do something better here. --A INPUT -p udp -j ACCEPT -<% else -%> - -# Accept incoming traffic on TCP ports: --A INPUT -p tcp --dport ssh -j ACCEPT --A INPUT -p tcp --dport smtp -j ACCEPT --A INPUT -p tcp --dport http -j ACCEPT --A INPUT -p tcp --dport https -j ACCEPT --A INPUT -p tcp --dport postgresql -j ACCEPT - -<% if @fqdn.include? "smokescreen" -%> -# Smokescreen proxy --A INPUT -p tcp --dport 4750 -j ACCEPT - -# Camo proxy --A INPUT -p tcp --dport 9292 -j ACCEPT -<% end -%> - -# statsd --A INPUT -p udp --dport 8125 -j ACCEPT -<% end -%> - -# Drop everything else --A INPUT -j LOGDROP --A FORWARD -j LOGDROP - -COMMIT