Skip to content

Commit

Permalink
Firewall update (#269)
Browse files Browse the repository at this point in the history
- Created functions for firewall type detection and opening a port.
- You can now easily open a port using the profile::firewall_open_port() function. See sample_website profile for examples.
- Updated code for sample website. Bit of a clean up job, now works on all OS types (ubuntu, rhel, centos & windows).
- Fixed a flapping corrective change with the firewallchain resource
- Commented out the SQL module in the Puppetfile to remove warning with 'puppet apply'. If you need this uncomment it on your deployment.
- Updated firewalld code to use a fork that support managing the package external to the module itself
- Other random style/syntax cleanup


* Package before class to fix initial run failure.
* Clean up Windows sample_website code
* Clean up Linux and Windows sample_website
* Comment out SQL module to reduce error noise
* update for better firewalld package  management
* custom fork of firewalld for package management
* Stop flapping corrective change
* correct syntax for Windows sample_website
* move firewall_type to function for reuse
* simplified functions
  • Loading branch information
psreed authored Nov 17, 2023
1 parent eb15fe2 commit 0b0f13c
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 97 deletions.
10 changes: 7 additions & 3 deletions Puppetfile
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ mod 'puppetlabs-servicenow_change_requests', '0.4.1'
mod 'puppetlabs-servicenow_cmdb_integration', '0.2.0'
mod 'puppetlabs-servicenow_reporting_integration', '1.0.0'
mod 'puppetlabs-splunk_hec', '1.4.0' # Missing requirement of puppetlabs-puppet_metrics_collector
mod 'puppetlabs-sqlserver', '4.1.0'
#mod 'puppetlabs-sqlserver', '4.1.0' # Uncomment if needed for a SQL Demo
mod 'puppetlabs-stdlib', '9.4.0'
mod 'puppetlabs-tomcat', '7.1.0'
mod 'puppetlabs-transition', '2.0.0'
Expand Down Expand Up @@ -88,7 +88,11 @@ mod 'lwf-remote_file', '1.1.3'
mod 'nexcess-auditd', '4.2.0' # Part of profile::compliance::hippa
mod 'puppet-archive', '7.0.0'
mod 'puppet-epel', '5.0.0'
mod 'puppet-firewalld', '5.0.0'

mod 'puppet-firewalld', # Using a custom fork of the firewalld for proper pacakge management / dependancy management
git: 'https://github.com/puppetlabs-seteam/puppet-firewalld.git',
branch: 'master'

mod 'puppet-gitlab', '8.1.0'
mod 'puppet-hiera', '5.0.1'
mod 'puppet-jenkins', '4.0.0' # Do we need this, it is out of date and requires java < 5.0.0, and zypprepo
Expand All @@ -110,7 +114,7 @@ mod 'reidmv-unzip', '0.1.2'
mod 'trlinkin-domain_membership', '1.1.2'
mod 'tse-time', '1.0.1'
mod 'tse-winntp', '1.0.1'
mod 'puppet-staging', '3.2.0'
mod 'puppet-staging', '3.2.0'
mod 'artsir-ansible_config', '1.1.3'

# This is missing dependency on mayflower-php, needs updated to use puppet-php at least
Expand Down
44 changes: 44 additions & 0 deletions site-modules/profile/functions/firewall_open_port.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function profile::firewall_open_port(String $name, String $protocol, Integer $port, String $description) >> Boolean {
$firewall_type = profile::firewall_type($facts['os']['name'], $facts['os']['release']['major'])
case $firewall_type {
'iptables': {
firewall { "200 Allow ${name}":
dport => $port,
proto => $protocol.downcase(),
jump => accept,
}
}
'firewalld': {
firewalld_port { "Allow ${name}":
ensure => present,
zone => 'public',
port => $port,
protocol => $protocol.downcase(),
}
}
'ufw': {
ufw_rule { "Allow ${name}":
ensure => present,
action => 'allow',
direction => 'in',
interface => undef,
to_ports_app => $port,
proto => $protocol.downcase(),
}
}
'windows': {
windows_firewall_rule { "Allow ${name} - Puppet Managed":
ensure => present,
direction => 'inbound',
action => 'allow',
enabled => true,
protocol => $protocol.downcase(),
local_port => String($port),
display_name => "${protocol.upcase()} ${port} - ${name} - Puppet Managed",
description => $description,
}
}
default: { fail("Firewall type could not be determined for '${facts['os']['name']} ${facts['os']['release']['major']}'") }
}
true
}
43 changes: 43 additions & 0 deletions site-modules/profile/functions/firewall_type.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
function profile::firewall_type(String $os, String $version) >> String {
$os_firewalls = {
'alma' => {
'8' => 'firewalld',
'9' => 'firewalld',
},
'centos' => {
'7' => 'iptables',
'8' => 'firewalld',
},
'oraclelinux' => {
'7' => 'iptables',
'8' => 'firewalld',
'9' => 'firewalld',
},
'redhat' => {
'7' => 'iptables',
'8' => 'firewalld',
'9' => 'firewalld',
},
'rocky' => {
'8' => 'firewalld',
'9' => 'firewalld',
},
'ubuntu' => {
'20.04' => 'ufw',
'22.04' => 'ufw',
},
'windows' => {
'10' => 'windows',
'11' => 'windows',
'2016' => 'windows',
'2019' => 'windows',
'2022' => 'windows',
},
}

if $os != undef and $version != undef {
$firewall_type = $os_firewalls[$os.downcase()][$version]
} else {
''
}
}
2 changes: 0 additions & 2 deletions site-modules/profile/manifests/app/sample_website.pp
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# @summary This profile installs a sample website
class profile::app::sample_website {

case $facts['kernel'] {
'windows': { include profile::app::sample_website::windows }
'Linux': { include profile::app::sample_website::linux }
default: {
fail('Unsupported kernel detected')
}
}

}
55 changes: 28 additions & 27 deletions site-modules/profile/manifests/app/sample_website/linux.pp
Original file line number Diff line number Diff line change
@@ -1,58 +1,59 @@
#
# Sample Apache Website managed by Puppet for Linux nodes
#
# @param doc_root
# Document root location on disk
# @param webserver_port
# Server access port for web traffic.
# @param website_source_dir
# Source location for content files
class profile::app::sample_website::linux (
String $doc_root = '/var/www/html',
Integer $webserver_port = 80,
String $website_source_dir = 'puppet:///modules/profile/app/sample_website',
Boolean $enable_monitoring = false,
String $doc_root = '/var/www/html',
Integer $webserver_port = 80,
String $website_source_dir = 'puppet:///modules/profile/app/sample_website',
) {

#if $enable_monitoring {
#sensu::subscription { 'apache': }
#}

class {'::profile::app::webserver::apache':
# Include the main Apache webserver management classification
class { 'profile::app::webserver::apache':
default_vhost => false,
}

# configure apache
# Set the desired configuration for the Website Virtual Host
apache::vhost { $facts['networking']['fqdn']:
port => $webserver_port,
docroot => $doc_root,
require => File[$doc_root],
options => ['-Indexes'],
error_documents => [
{ 'error_code' => '404', 'document' => '/404.html' },
{ 'error_code' => '403', 'document' => '/403.html' }
{ 'error_code' => '403', 'document' => '/403.html' },
],
}

firewall { '100 allow http and https access':
dport => $webserver_port,
proto => tcp,
jump => accept,
}

# Configure the doc_root folder for the Website
file { $website_source_dir:
ensure => directory,
owner => $::apache::user,
group => $::apache::group,
owner => $apache::user,
group => $apache::group,
mode => '0755',
path => $doc_root,
source => $website_source_dir,
recurse => true,
}

# Manage the index.html file on the Website using a provided Puppet EPP template.
file { "${doc_root}/index.html":
ensure => file,
content => epp('profile/app/sample_website.html.epp'),
}

file { "${doc_root}/403.html":
ensure => file,
content => epp('profile/app/403.html.epp'),
# Manage the error files on the Website using a provided Puppet EPP template.
['403','404'].each | String $err_no | {
file { "${doc_root}/${err_no}.html":
ensure => file,
content => epp("profile/app/${err_no}.html.epp"),
}
}

file { "${doc_root}/404.html":
ensure => file,
content => epp('profile/app/404.html.epp'),
}
# Automatically open firewall port to allow access
profile::firewall_open_port('Website Access','tcp',$webserver_port,'Webserver Access')
}
56 changes: 28 additions & 28 deletions site-modules/profile/manifests/app/sample_website/windows.pp
Original file line number Diff line number Diff line change
@@ -1,62 +1,62 @@
#
# Sample IIS Website managed by Puppet for Windows nodes
#
# @param doc_root
# Document Root location on disk
# @param webserver_port
# Server access port for web traffic.
# @param app_pool
# Application Pool Name
# @param website_source_dir
# Source location for content files
class profile::app::sample_website::windows (
String $doc_root = 'C:\inetpub\wwwroot\sample_website',
Integer $webserver_port = 80, # change this default value in Hiera common.yaml
String $apppool = 'sample_website',
String $website_source_dir = 'puppet:///modules/profile/app/sample_website',
Boolean $enable_monitoring = false,
String $doc_root = 'C:\inetpub\wwwroot\sample_website',
Integer $webserver_port = 80,
String $app_pool = 'sample_website',
String $website_source_dir = 'puppet:///modules/profile/app/sample_website',
) {

#if $enable_monitoring {
#sensu::subscription { 'iis': }
#}

class{'::profile::app::webserver::iis':
# Include the main IIS webserver management classification
class { 'profile::app::webserver::iis':
default_website => false,
}

# configure iis
iis_application_pool {'sample_website':
# Create the Application Pool for the Website
iis_application_pool { 'sample_website':
require => [
Class['::profile::app::webserver::iis'],
Class['profile::app::webserver::iis'],
],
}

# Set the desired configuration for the Website
iis_site { 'sample_website':
ensure => 'started',
physicalpath => $doc_root,
applicationpool => $apppool,
applicationpool => $app_pool,
bindings => [
{
'bindinginformation' => "*:$webserver_port:",
'protocol' => 'http',
'bindinginformation' => "*:${webserver_port}:",
'protocol' => 'http',
},
],
require => [
Iis_application_pool['sample_website']
],
}

windows_firewall::exception { 'IIS':
ensure => present,
direction => 'in',
action => 'allow',
enabled => true,
protocol => 'TCP',
local_port => $webserver_port,
display_name => "HTTP_$webserver_port", # generate a unique inbound rule. this new rule per port value is just for demo purposes
description => 'Inbound rule for HTTP Server',
}

# Configure the doc_root folder for the Website
file { $website_source_dir:
ensure => directory,
path => $doc_root,
source => $website_source_dir,
recurse => true,
}

# Manage the index.html file on the Website using a provided Puppet EPP template.
file { "${doc_root}/index.html":
ensure => file,
content => epp('profile/app/sample_website.html.epp'),
}

# Add a firewall rule to permit access to the Website Port
profile::firewall_open_port('IIS','tcp',$webserver_port,'Inbound rule for HTTP Server')
}
37 changes: 1 addition & 36 deletions site-modules/profile/manifests/platform/baseline/firewall.pp
Original file line number Diff line number Diff line change
Expand Up @@ -27,43 +27,8 @@
Array[Hash] $allow_ingress_linux_default = [],
) {
# Host based firewall management varies by OS type/version, we need to determine the firewall type to manage
$os_firewalls = {
'alma' => {
'8' => 'firewalld',
'9' => 'firewalld',
},
'centos' => {
'7' => 'iptables',
'8' => 'firewalld',
},
'oraclelinux' => {
'7' => 'iptables',
'8' => 'firewalld',
'9' => 'firewalld',
},
'redhat' => {
'7' => 'iptables',
'8' => 'firewalld',
'9' => 'firewalld',
},
'rocky' => {
'8' => 'firewalld',
'9' => 'firewalld',
},
'ubuntu' => {
'20.04' => 'ufw',
'22.04' => 'ufw',
},
'windows' => {
'10' => 'windows',
'11' => 'windows',
'2016' => 'windows',
'2019' => 'windows',
'2022' => 'windows',
},
}

$firewall_type = $os_firewalls[$facts['os']['name'].downcase()][$facts['os']['release']['major']]
$firewall_type = profile::firewall_type($facts['os']['name'], $facts['os']['release']['major'])

# Apply the applicable firewall type
case $firewall_type {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@
Boolean $allow_ingress_icmpv4 = $profile::platform::baseline::firewall::allow_ingress_icmpv4,
Array[Hash] $allow_ingress = $profile::platform::baseline::firewall::allow_ingress_linux_default + $profile::platform::baseline::firewall::allow_ingress, #lint:ignore:140chars
) {
ensure_resource('package','firewalld', { ensure => present })

class { 'firewalld':
service_ensure => running,
service_enable => true,
manage_package => false,
purge_direct_rules => true,
purge_direct_chains => true,
purge_direct_passthroughs => true,
purge_unknown_ipsets => true,
require => Package['firewalld'],
}

$icmp_block_inversion = $allow_ingress_icmpv4 ? { true => false, false => true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
}

resources { 'firewall': purge => true, }
resources { 'firewallchain': purge => true, }

firewallchain { 'INPUT:filter:IPv4':
ensure => present,
Expand Down

0 comments on commit 0b0f13c

Please sign in to comment.