From b12c808f6f5d4d0817e98309e1b9b4b3685a1984 Mon Sep 17 00:00:00 2001 From: Trevor Vaughan Date: Thu, 12 Dec 2019 14:37:12 -0500 Subject: [PATCH] Add support for EL8 * Added OEL to the metadata.json * Added a very basic acceptance test to test the main components of the module. This should be expanded into multi-node tests later. * Added a REFERENCE.md * Updated the README.md to point to the REFERENCE.md and added instructions on how to run the acceptance test. Closes #246 --- .github/CONTRIBUTING.md | 6 +- .msync.yml | 2 +- .rubocop.yml | 7 +- .sync.yml | 8 + Gemfile | 4 +- README.md | 22 +- REFERENCE.md | 965 ++++++++++++++++++ .../firewalld_direct_purge/firewall_cmd.rb | 4 +- metadata.json | 13 +- spec/acceptance/00_default_spec.rb | 64 ++ spec/acceptance/init_spec.rb | 18 - spec/acceptance/nodesets/default.yml | 17 +- spec/spec_helper_acceptance.rb | 16 +- .../type/firewalld_direct_chain_spec.rb | 14 +- .../type/firewalld_direct_passthrough_spec.rb | 12 +- .../puppet/type/firewalld_direct_rule_spec.rb | 12 +- spec/unit/puppet/type/firewalld_ipset_spec.rb | 18 +- spec/unit/puppet/type/firewalld_port_spec.rb | 12 +- .../puppet/type/firewalld_rich_rule_spec.rb | 38 +- .../puppet/type/firewalld_service_spec.rb | 12 +- spec/unit/puppet/type/firewalld_zone_spec.rb | 14 +- 21 files changed, 1167 insertions(+), 111 deletions(-) create mode 100644 REFERENCE.md create mode 100644 spec/acceptance/00_default_spec.rb delete mode 100644 spec/acceptance/init_spec.rb diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index f3ffb570..2240a970 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -256,18 +256,20 @@ Beaker also supports docker containers. We also use that in our automated CI pipeline at [travis-ci](http://travis-ci.org). To use that instead of Vagrant: ```sh -PUPPET_INSTALL_TYPE=agent BEAKER_IS_PE=no BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=debian9-64{hypervisor=docker} BEAKER_destroy=yes bundle exec rake beaker +PUPPET_INSTALL_TYPE=agent BEAKER_IS_PE=no BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_debug=true BEAKER_setfile=debian10-64{hypervisor=docker} BEAKER_destroy=yes bundle exec rake beaker ``` -You can replace the string `debian9` with any common operating system. +You can replace the string `debian10` with any common operating system. The following strings are known to work: * ubuntu1604 * ubuntu1804 * debian8 * debian9 +* debian10 * centos6 * centos7 +* centos8 The easiest way to debug in a docker container is to open a shell: diff --git a/.msync.yml b/.msync.yml index e8e87038..2825b0cb 100644 --- a/.msync.yml +++ b/.msync.yml @@ -1 +1 @@ -modulesync_config_version: '2.10.1' +modulesync_config_version: '2.11.0' diff --git a/.rubocop.yml b/.rubocop.yml index 2c75f15d..c2ebc88d 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,7 @@ require: rubocop-rspec AllCops: - TargetRubyVersion: 2.1 +# Puppet Server 5 defaults to jruby 1.7 so TargetRubyVersion must stay at 1.9 until we drop support for puppet 5 + TargetRubyVersion: 1.9 Include: - ./**/*.rb Exclude: @@ -13,10 +14,6 @@ AllCops: - Rakefile - Guardfile - Vagrantfile - -Style/SymbolArray: - Enabled: false - Lint/ConditionPosition: Enabled: True diff --git a/.sync.yml b/.sync.yml index 846ac58c..55473bbf 100644 --- a/.sync.yml +++ b/.sync.yml @@ -18,6 +18,14 @@ spec/acceptance/nodesets/ec2/windows-2016-base-x64.yml: spec/acceptance/nodesets/archlinux-2-x64.yml: delete: true +Gemfile: + optional: + ':test': + - gem: 'mocha' + version: '~> 1.10.0' + ':system_tests': + - gem: 'beaker-vagrant' + .rubocop.yml: default_configs: Style/SymbolArray: diff --git a/Gemfile b/Gemfile index 50a90301..e2acb6bb 100644 --- a/Gemfile +++ b/Gemfile @@ -28,10 +28,10 @@ group :test do gem 'redcarpet', :require => false gem 'rubocop', '~> 0.49.1', :require => false gem 'rubocop-rspec', '~> 1.15.0', :require => false - gem 'mocha', '~> 1.4.0', :require => false gem 'coveralls', :require => false gem 'simplecov-console', :require => false gem 'parallel_tests', :require => false + gem 'mocha', '~> 1.10.0', :require => false end group :development do @@ -62,6 +62,8 @@ group :system_tests do gem 'rbnacl', '>= 4', :require => false gem 'rbnacl-libsodium', :require => false gem 'bcrypt_pbkdf', :require => false + gem 'ed25519', :require => false + gem 'beaker-vagrant', :require => false end group :release do diff --git a/README.md b/README.md index 4c7301f6..d0758325 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ## Description -This module manages firewalld, the userland interface that replaces iptables and ships with RHEL7. The module manages firewalld itself as well as providing types and providers for managing firewalld zones, ports, and rich rules. +This module manages firewalld, the userland interface that replaces iptables and ships with RHEL7+. The module manages firewalld itself as well as providing types and providers for managing firewalld zones, ports, and rich rules. ## Compatibility @@ -531,8 +531,28 @@ firewalld::direct_passthroughs: * `args`: Name of the passthroughhrough to add (e.g: -A OUTPUT -j OUTPUT_filter) +## Testing +### Unit Testing +Unit tests can be executed by running the following commands: + * `bundle install` + * `bundle exec rake spec` + +### Acceptance Testing + +Acceptance tests are performed using [Beaker](https://github.com/puppetlabs/beaker) and require [Vagrant](https://vagrantup.com) and [VirtualBox](https://www.virtualbox.org) to run successfully. + +It is **HIGHLY RECOMMENDED** that you use the upstream Vagrant package and not one from your OS provider. + +To run the acceptance tests: + * `bundle install` + * `bundle exec rake beaker` + +To leave the Vagrant hosts running on failure for debugging: + * `BEAKER_destroy=onpass bundle exec rake beaker` + * `cd .vagrant/beaker_vagrant_files/default.yml` + * `vagrant ssh ` # Author diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 00000000..c0ad9e7e --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,965 @@ +# Reference + + +## Table of Contents + +**Classes** + +* [`firewalld`](#firewalld): == Class: firewalld Manage the firewalld service See the README.md for usage instructions for the firewalld_zone and firewalld_rich_rule ty + +**Defined types** + +* [`firewalld::custom_service`](#firewalldcustom_service): == Type: firewalld::custom_service Creates a new service definition for use in firewalld See the README.md for usage instructions for this + +**Resource types** + +* [`firewalld_direct_chain`](#firewalld_direct_chain): Allow to create a custom chain in iptables/ip6tables/ebtables using firewalld direct interface. Example: firewalld_direct_chain {'Add c +* [`firewalld_direct_passthrough`](#firewalld_direct_passthrough): Allow to create a custom passthroughhrough traffic in iptables/ip6tables/ebtables using firewalld direct interface. Example: firewalld_ +* [`firewalld_direct_purge`](#firewalld_direct_purge): Allow to purge direct rules in iptables/ip6tables/ebtables using firewalld direct interface. Example: firewalld_direct_purge {'chain': +* [`firewalld_direct_rule`](#firewalld_direct_rule): Allow to pass rules directly to iptables/ip6tables/ebtables using firewalld direct interface. Example: firewalld_direct_rule {'Allow ou +* [`firewalld_ipset`](#firewalld_ipset): Configure IPsets in Firewalld Example: firewalld_ipset {'internal net': ensure => 'present', type => 'hash:net', +* [`firewalld_port`](#firewalld_port): Assigns a port to a specific firewalld zone. firewalld_port will autorequire the firewalld_zone specified in the zone parameter so there is n +* [`firewalld_rich_rule`](#firewalld_rich_rule): Manages firewalld rich rules. firewalld_rich_rules will autorequire the firewalld_zone specified in the zone parameter so there is no need t +* [`firewalld_service`](#firewalld_service): Assigns a service to a specific firewalld zone. firewalld_service will autorequire the firewalld_zone specified in the zone parameter and +* [`firewalld_zone`](#firewalld_zone): Creates and manages firewald zones. Note that setting ensure => 'absent' to the built in firewalld zones will not work, and will generate an + +## Classes + +### firewalld + +== Class: firewalld + +Manage the firewalld service + +See the README.md for usage instructions for the firewalld_zone and +firewalld_rich_rule types + +=== Examples + + Standard: + include firewalld + + Command line only, no GUI components: + class{'firewalld': + } + + With GUI components + class{'firewalld': + install_gui => true, + } + + + +=== Authors + +Craig Dunn + +=== Copyright + +Copyright 2015 Craig Dunn + +#### Parameters + +The following parameters are available in the `firewalld` class. + +##### `package_ensure` + +Data type: `Enum['present','absent','latest','installed']` + + + +Default value: 'installed' + +##### `package` + +Data type: `String` + + + +Default value: 'firewalld' + +##### `service_ensure` + +Data type: `Stdlib::Ensure::Service` + + + +Default value: 'running' + +##### `config_package` + +Data type: `String` + + + +Default value: 'firewall-config' + +##### `install_gui` + +Data type: `Boolean` + + + +Default value: `false` + +##### `service_enable` + +Data type: `Boolean` + + + +Default value: `true` + +##### `zones` + +Data type: `Hash` + + + +Default value: {} + +##### `ports` + +Data type: `Hash` + + + +Default value: {} + +##### `services` + +Data type: `Hash` + + + +Default value: {} + +##### `rich_rules` + +Data type: `Hash` + + + +Default value: {} + +##### `custom_services` + +Data type: `Hash` + + + +Default value: {} + +##### `ipsets` + +Data type: `Hash` + + + +Default value: {} + +##### `direct_rules` + +Data type: `Hash` + + + +Default value: {} + +##### `direct_chains` + +Data type: `Hash` + + + +Default value: {} + +##### `direct_passthroughs` + +Data type: `Hash` + + + +Default value: {} + +##### `purge_direct_rules` + +Data type: `Boolean` + + + +Default value: `false` + +##### `purge_direct_chains` + +Data type: `Boolean` + + + +Default value: `false` + +##### `purge_direct_passthroughs` + +Data type: `Boolean` + + + +Default value: `false` + +##### `purge_unknown_ipsets` + +Data type: `Boolean` + + + +Default value: `false` + +##### `default_zone` + +Data type: `Optional[String]` + + + +Default value: `undef` + +##### `log_denied` + +Data type: `Optional[Enum['off','all','unicast','broadcast','multicast']]` + + + +Default value: `undef` + +##### `cleanup_on_exit` + +Data type: `Optional[Enum['yes', 'no']]` + + + +Default value: `undef` + +##### `minimal_mark` + +Data type: `Optional[Integer]` + + + +Default value: `undef` + +##### `lockdown` + +Data type: `Optional[Enum['yes', 'no']]` + + + +Default value: `undef` + +##### `ipv6_rpfilter` + +Data type: `Optional[Enum['yes', 'no']]` + + + +Default value: `undef` + +##### `default_service_zone` + +Data type: `Optional[String]` + + + +Default value: `undef` + +##### `default_port_zone` + +Data type: `Optional[String]` + + + +Default value: `undef` + +##### `default_port_protocol` + +Data type: `Optional[String]` + + + +Default value: `undef` + +## Defined types + +### firewalld::custom_service + +== Type: firewalld::custom_service + +Creates a new service definition for use in firewalld + +See the README.md for usage instructions for this defined type + +=== Examples + + firewalld::custom_service{'My Custom Service': + short => 'MyService', + description => 'My Custom Service is a daemon that does whatever', + port => [ + { + 'port' => '1234' + 'protocol' => 'tcp' + }, + { + 'port' => '1234' + 'protocol' => 'udp' + }, + ], + module => ['nf_conntrack_netbios_ns'], + destination => { + 'ipv4' => '127.0.0.1', + 'ipv6' => '::1' + } + } + +=== Authors + +Andrew Patik + +#### Parameters + +The following parameters are available in the `firewalld::custom_service` defined type. + +##### `short` + +Data type: `String` + + + +Default value: $name + +##### `description` + +Data type: `Optional[String]` + + + +Default value: `undef` + +##### `port` + +Data type: `Optional[Array[Hash]]` + + + +Default value: `undef` + +##### `module` + +Data type: `Optional[Array[String]]` + + + +Default value: `undef` + +##### `destination` + +Data type: `Optional[Hash[ + Enum['ipv4', 'ipv6'], + String + ]]` + + + +Default value: `undef` + +##### `filename` + +Data type: `String` + + + +Default value: $short + +##### `config_dir` + +Data type: `Stdlib::Unixpath` + + + +Default value: '/etc/firewalld/services' + +##### `ensure` + +Data type: `Enum['present','absent']` + + + +Default value: 'present' + +## Resource types + +### firewalld_direct_chain + +Allow to create a custom chain in iptables/ip6tables/ebtables using firewalld direct interface. + +Example: + + firewalld_direct_chain {'Add custom chain LOG_DROPS': + name => 'LOG_DROPS', + ensure => 'present', + inet_protocol => 'ipv4', + table => 'filter' + } + +#### Properties + +The following properties are available in the `firewalld_direct_chain` type. + +##### `ensure` + +Valid values: present, absent + +The basic property that the resource should be in. + +Default value: present + +#### Parameters + +The following parameters are available in the `firewalld_direct_chain` type. + +##### `name` + +Name of the chain eg: LOG_DROPS + +##### `inet_protocol` + +Valid values: ipv4, ipv6 + +namevar + +Name of the TCP/IP protocol to use (e.g: ipv4, ipv6) + +Default value: ipv4 + +##### `table` + +namevar + +Name of the table type to add (e.g: filter, nat, mangle, raw) + +### firewalld_direct_passthrough + +Allow to create a custom passthroughhrough traffic in iptables/ip6tables/ebtables using firewalld direct interface. + +Example: + + firewalld_direct_passthrough {'Forward traffic from OUTPUT to OUTPUT_filter': + ensure => 'present', + inet_protocol => 'ipv4', + args => '-A OUTPUT -j OUTPUT_filter', + } + +Or using namevar + + firewalld_direct_passthrough {'-A OUTPUT -j OUTPUT_filter': + ensure => 'present', + } + +#### Properties + +The following properties are available in the `firewalld_direct_passthrough` type. + +##### `ensure` + +Valid values: present, absent + +The basic property that the resource should be in. + +Default value: present + +#### Parameters + +The following parameters are available in the `firewalld_direct_passthrough` type. + +##### `inet_protocol` + +Valid values: ipv4, ipv6 + +Name of the TCP/IP protocol to use (e.g: ipv4, ipv6) + +Default value: ipv4 + +##### `args` + +namevar + +Name of the passthroughhrough to add (e.g: -A OUTPUT -j OUTPUT_filter) + +### firewalld_direct_purge + +Allow to purge direct rules in iptables/ip6tables/ebtables using firewalld direct interface. + +Example: + + firewalld_direct_purge {'chain': } + firewalld_direct_purge {'passthrough': } + firewalld_direct_purge {'rule': } + +#### Properties + +The following properties are available in the `firewalld_direct_purge` type. + +##### `ensure` + +Valid values: purgable, purged + +The basic property that the resource should be in. + +Default value: purged + +#### Parameters + +The following parameters are available in the `firewalld_direct_purge` type. + +##### `purge` + +Valid values: `true`, `false` + + + +Default value: `true` + +##### `name` + +Valid values: chain, passthrough, rule + +namevar + +Type of resource to purge, valid values are 'chain', 'passthrough' and 'rule' + +### firewalld_direct_rule + +Allow to pass rules directly to iptables/ip6tables/ebtables using firewalld direct interface. + +Example: + + firewalld_direct_rule {'Allow outgoing SSH connection': + ensure => 'present', + inet_protocol => 'ipv4', + table => 'filter', + chain => 'OUTPUT', + priority => 1, + args => '-p tcp --dport=22 -j ACCEPT', + } + +#### Properties + +The following properties are available in the `firewalld_direct_rule` type. + +##### `ensure` + +Valid values: present, absent + +The basic property that the resource should be in. + +Default value: present + +#### Parameters + +The following parameters are available in the `firewalld_direct_rule` type. + +##### `name` + +namevar + +Name of the rule resource in Puppet + +##### `inet_protocol` + +Valid values: ipv4, ipv6 + +Name of the TCP/IP protocol to use (e.g: ipv4, ipv6) + +Default value: ipv4 + +##### `table` + +Name of the table type to add (e.g: filter, nat, mangle, raw) + +##### `chain` + +Name of the chain type to add (e.g: INPUT, OUTPUT, FORWARD) + +##### `priority` + +The priority number of the rule (e.g: 0, 1, 2, ... 99) + +##### `args` + + can be all iptables, ip6tables and ebtables command line arguments + +### firewalld_ipset + +Configure IPsets in Firewalld + +Example: + firewalld_ipset {'internal net': + ensure => 'present', + type => 'hash:net', + family => 'inet', + entries => ['192.168.0.0/24'] + } + +#### Properties + +The following properties are available in the `firewalld_ipset` type. + +##### `ensure` + +Valid values: present, absent + +The basic property that the resource should be in. + +Default value: present + +##### `entries` + +Array of ipset entries + +##### `family` + +Valid values: inet6, inet + +Protocol family of the IPSet + +##### `hashsize` + +Initial hash size of the IPSet + +##### `maxelem` + +Valid values: %r{^[1-9]\d*$} + +Maximal number of elements that can be stored in the set + +##### `timeout` + +Valid values: %r{^\d+$} + +Timeout in seconds before entries expiry. 0 means entry is permanent + +#### Parameters + +The following parameters are available in the `firewalld_ipset` type. + +##### `name` + +namevar + +Name of the IPset + +##### `type` + +Valid values: bitmap:ip, bitmap:ip,mac, bitmap:port, hash:ip, hash:ip,mark, hash:ip,port, hash:ip,port,ip, hash:ip,port,net, hash:mac, hash:net, hash:net,iface, hash:net,net, hash:net,port, hash:net,port,net, list:set + +Type of the ipset (default: hash:ip) + +Default value: hash:ip + +##### `options` + +Hash of options for the IPset, eg { 'family' => 'inet6' } + +##### `manage_entries` + +Valid values: `true`, `false`, yes, no + +Should we manage entries in this ipset or leave another process manage those entries + +Default value: `true` + +### firewalld_port + +Assigns a port to a specific firewalld zone. +firewalld_port will autorequire the firewalld_zone specified in the zone parameter so there is no need to add dependencies for this + +Example: + + firewalld_port {'Open port 8080 in the public Zone': + ensure => 'present', + zone => 'public', + port => 8080, + protocol => 'tcp', + } + +#### Properties + +The following properties are available in the `firewalld_port` type. + +##### `ensure` + +Valid values: present, absent + +The basic property that the resource should be in. + +Default value: present + +#### Parameters + +The following parameters are available in the `firewalld_port` type. + +##### `name` + +namevar + +Name of the port resource in Puppet + +##### `zone` + +Name of the zone to which you want to add the port + +##### `port` + +Specify the element as a port + +##### `protocol` + +Specify the element as a protocol + +### firewalld_rich_rule + +Manages firewalld rich rules. + +firewalld_rich_rules will autorequire the firewalld_zone specified in the zone parameter so there is no need to add dependencies for this + +Example: + + firewalld_rich_rule { 'Accept SSH from barny': + ensure => present, + zone => 'restricted', + source => '192.168.1.2/32', + service => 'ssh', + action => 'accept', + } + +#### Properties + +The following properties are available in the `firewalld_rich_rule` type. + +##### `ensure` + +Valid values: present, absent + +The basic property that the resource should be in. + +Default value: present + +#### Parameters + +The following parameters are available in the `firewalld_rich_rule` type. + +##### `name` + +namevar + +Name of the rule resource in Puppet + +##### `zone` + +Name of the zone + +##### `family` + +Valid values: ipv4, ipv6 + +IP family, one of ipv4 or ipv6, defauts to ipv4 + +Default value: ipv4 + +##### `source` + +Specify source address, this can be a string of the IP address or a hash containing other options + +##### `dest` + +Specify destination address, this can be a string of the IP address or a hash containing other options + +##### `service` + +Specify the element as a service + +##### `port` + +Specify the element as a port + +##### `protocol` + +Specify the element as a protocol + +##### `icmp_block` + +Specify the element as an icmp-block + +##### `masquerade` + +Specify the element as masquerade + +##### `forward_port` + +Specify the element as forward-port + +##### `log` + +doc + +##### `audit` + +doc + +##### `action` + + + +##### `raw_rule` + +Manage the entire rule as one string - this is used internally by firwalld_zone to +handle pruning of rules + +### firewalld_service + +Assigns a service to a specific firewalld zone. + firewalld_service will autorequire the firewalld_zone specified in the zone parameter and the firewalld::custom_service +specified in the service parameter, so there is no need to add dependencies for this + + Example: + + firewalld_service {'Allow SSH in the public Zone': + ensure => 'present', + zone => 'public', + service => 'ssh', + } + +#### Properties + +The following properties are available in the `firewalld_service` type. + +##### `ensure` + +Valid values: present, absent + +The basic property that the resource should be in. + +Default value: present + +#### Parameters + +The following parameters are available in the `firewalld_service` type. + +##### `name` + +namevar + +Name of the service resource in Puppet + +##### `service` + +Name of the service to add + +##### `zone` + +Name of the zone to which you want to add the service + +### firewalld_zone + +Creates and manages firewald zones. +Note that setting ensure => 'absent' to the built in firewalld zones will +not work, and will generate an error. This is a limitation of firewalld itself, not the module. + +Example: + + firewalld_zone { 'restricted': + ensure => present, + target => '%%REJECT%%', + interfaces => [], + sources => [], + purge_rich_rules => true, + purge_services => true, + purge_ports => true, + icmp_blocks => 'router-advertisement' + } + +#### Properties + +The following properties are available in the `firewalld_zone` type. + +##### `ensure` + +Valid values: present, absent + +The basic property that the resource should be in. + +Default value: present + +##### `target` + +Specify the target for the zone + +##### `interfaces` + +Specify the interfaces for the zone + +##### `masquerade` + +Valid values: `true`, `false` + +Can be set to true or false, specifies whether to add or remove masquerading from the zone + +##### `sources` + +Specify the sources for the zone + +##### `icmp_blocks` + +Specify the icmp-blocks for the zone. Can be a single string specifying one icmp type, +or an array of strings specifying multiple icmp types. Any blocks not specified here will be removed + +##### `purge_rich_rules` + +Valid values: `false`, `true` + +When set to true any rich_rules associated with this zone +that are not managed by Puppet will be removed. + +##### `purge_services` + +Valid values: `false`, `true` + +When set to true any services associated with this zone +that are not managed by Puppet will be removed. + +##### `purge_ports` + +Valid values: `false`, `true` + +When set to true any ports associated with this zone +that are not managed by Puppet will be removed. + +#### Parameters + +The following parameters are available in the `firewalld_zone` type. + +##### `name` + +namevar + +Name of the rule resource in Puppet + +##### `zone` + +Name of the zone + +##### `description` + +Description of the zone to add + +##### `short` + +Short description of the zone to add + diff --git a/lib/puppet/provider/firewalld_direct_purge/firewall_cmd.rb b/lib/puppet/provider/firewalld_direct_purge/firewall_cmd.rb index dfe2e171..d7f7a592 100644 --- a/lib/puppet/provider/firewalld_direct_purge/firewall_cmd.rb +++ b/lib/puppet/provider/firewalld_direct_purge/firewall_cmd.rb @@ -8,14 +8,14 @@ desc 'Meta provider to the firewalld_direct_purge type' def get_instances_of(restype) - raise Puppet::Error, "Unknown type #{restype}" unless %i[chain passthrough rule].include?(restype) + raise Puppet::Error, "Unknown type #{restype}" unless [:chain, :assthrough, :rule].include?(restype) perm = execute_firewall_cmd(['--direct', "--get-all-#{restype}s"], nil).split(%r{\n}) curr = execute_firewall_cmd(['--direct', "--get-all-#{restype}s"], nil, false).split(%r{\n}) [perm, curr].flatten.uniq end def purge_resources(restype, args) - raise Puppet::Error, "Unknown type #{restype}" unless %i[chain passthrough rule].include?(restype) + raise Puppet::Error, "Unknown type #{restype}" unless [:chain, :passthrough, :rule].include?(restype) execute_firewall_cmd(['--direct', "--remove-#{restype}", parse_args(args)], nil) end end diff --git a/metadata.json b/metadata.json index 40323801..4da8f882 100644 --- a/metadata.json +++ b/metadata.json @@ -22,13 +22,22 @@ { "operatingsystem": "RedHat", "operatingsystemrelease": [ - "7" + "7", + "8" ] }, { "operatingsystem": "CentOS", "operatingsystemrelease": [ - "7" + "7", + "8" + ] + }, + { + "operatingsystem": "OracleLinux", + "operatingsystemrelease": [ + "7", + "8" ] } ], diff --git a/spec/acceptance/00_default_spec.rb b/spec/acceptance/00_default_spec.rb new file mode 100644 index 00000000..040b53e5 --- /dev/null +++ b/spec/acceptance/00_default_spec.rb @@ -0,0 +1,64 @@ +require 'spec_helper_acceptance' + +describe 'firewalld', unless: UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do + # This is a VERY MINIMAL test + # + # Additional tests should be added to cover all module capabilities + hosts.each do |host| + context "on #{host}" do + let(:manifest) do + <<-EOM + class { 'firewalld': + lockdown => 'yes', + default_zone => 'test', + log_denied => 'unicast' + } + + firewalld_zone { 'test': + ensure => 'present', + purge_rich_rules => true, + purge_services => true, + purge_ports => true, + target => 'DROP', + require => Service['firewalld'] + } + + firewalld::custom_service { 'test_sshd': + short => 'test_sshd', + description => 'Test SSH Access', + port => [{ 'port' => '22', 'protocol' => 'tcp' }], + require => Service['firewalld'] + } + + firewalld_service { 'test_sshd': + zone => 'test', + require => Service['firewalld'] + } + EOM + end + + it 'runs successfully' do + apply_manifest_on(host, manifest, catch_failures: true) + end + + it 'is idempotent' do + apply_manifest_on(host, manifest, catch_changes: true) + end + + it 'is running firewalld' do + svc = YAML.load(on(host, 'puppet resource service firewalld --to_yaml').output) + expect(svc['service']['firewalld']['ensure']).to match('running') + end + + it 'has "test" as the default zone' do + default_zone = on(host, 'firewall-cmd --get-default-zone').output.strip + expect(default_zone).to eq('test') + end + + it 'has the "test_sshd" service in the "test" zone' do + test_services = on(host, 'firewall-cmd --list-services --zone=test').output.strip.split(%r{\s+}) + expect(test_services).to include('test_sshd') + end + end + end +end diff --git a/spec/acceptance/init_spec.rb b/spec/acceptance/init_spec.rb deleted file mode 100644 index d4c9b8eb..00000000 --- a/spec/acceptance/init_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'spec_helper_acceptance' - -describe 'firewalld', unless: UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do - context 'running with defaults' do - it 'runs successfully' do - pp = 'include firewalld' - # Apply... - apply_manifest(pp, catch_failures: true) - # ...twice and see if this is idempotent - expect(apply_manifest(pp, catch_failures: true).exit_code).to be_zero - end - - describe command('firewall-cmd --list-ports') do - its(:stdout) { is_expected.to match %r{6379} } - its(:stdout) { is_expected.to match %r{5666} } - end - end -end diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml index 6100318c..1eb8ecb8 100644 --- a/spec/acceptance/nodesets/default.yml +++ b/spec/acceptance/nodesets/default.yml @@ -1,6 +1,19 @@ HOSTS: centos-7-x64: - platform: el-7-x86_64 - box: puppetlabs/centos-7.0-64-nocm + roles: + - default + platform: el-7-x86_64 + box: centos/7 hypervisor: vagrant + centos-8-x64: + platform: el-8-x86_64 + box: centos/8 + hypervisor: vagrant + +CONFIG: + type: aio + vagrant_memsize: 256 + log_level: verbose + synced_folder: disabled + puppet_collection: puppet6 diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index bfaae4dc..ea2ce17a 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,29 +1,29 @@ require 'beaker-rspec' -require 'beaker/puppet_install_helper' require 'pry' UNSUPPORTED_PLATFORMS = %w[windows Darwin].freeze unless ENV['RS_PROVISION'] == 'no' || ENV['BEAKER_provision'] == 'no' - environment = ENV['http_proxy'] ? { http_proxy: ENV['http_proxy'] } : {} + require 'beaker/puppet_install_helper' - run_puppet_install_helper + run_puppet_install_helper('agent', ENV['PUPPET_VERSION']) RSpec.configure do |c| # Project root - proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) + proj_root = File.expand_path(File.join(__dir__, '..')) # Readable test descriptions c.formatter = :documentation + # Don't burn resources if we don't have to + c.fail_fast = true + # Configure all nodes in nodeset c.before :suite do - puppet_module_install(source: proj_root, module_name: 'firewalld') hosts.each do |host| - scp_to(host, File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec/fixtures/hiera/hiera.yaml')), '/etc/puppetlabs/code/hiera.yaml') - scp_to(host, File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec/fixtures/hieradata/')), '/etc/puppetlabs/code/environments/production/') - on host, '/opt/puppetlabs/bin/puppet module install puppetlabs/stdlib', environment: environment, acceptable_exit_codes: [0, 1] + install_dev_puppet_module_on(host, source: proj_root, module_name: 'firewalld') + install_puppet_module_via_pmt_on(host, module_name: 'puppetlabs/stdlib') end end end diff --git a/spec/unit/puppet/type/firewalld_direct_chain_spec.rb b/spec/unit/puppet/type/firewalld_direct_chain_spec.rb index 00b9c8da..172f27b0 100644 --- a/spec/unit/puppet/type/firewalld_direct_chain_spec.rb +++ b/spec/unit/puppet/type/firewalld_direct_chain_spec.rb @@ -7,7 +7,7 @@ context 'with no params' do describe 'when validating attributes' do - %i[name inet_protocol table].each do |param| + [:name, :inet_protocol, :table].each do |param| it "should have a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:param) end @@ -16,7 +16,7 @@ describe 'namevar validation' do it 'has :name, :inet_protocol and :table as its namevars' do - expect(described_class.key_attributes).to eq(%i[name inet_protocol table]) + expect(described_class.key_attributes).to eq([:name, :inet_protocol, :table]) end it 'uses the title as the name when non-delimited' do @@ -52,16 +52,16 @@ context 'autorequires' do # rubocop:disable RSpec/InstanceVariable before do - @firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') + firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource(@firewalld_service) + @catalog.add_resource(firewalld_service) end it 'autorequires the firewalld service' do - @resource = described_class.new(name: 'ipv4:filter:LOG_DROPS') - @catalog.add_resource(@resource) + resource = described_class.new(name: 'ipv4:filter:LOG_DROPS') + @catalog.add_resource(resource) - expect(@resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') + expect(resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') end # rubocop:enable RSpec/InstanceVariable end diff --git a/spec/unit/puppet/type/firewalld_direct_passthrough_spec.rb b/spec/unit/puppet/type/firewalld_direct_passthrough_spec.rb index e54a6539..88b5758a 100644 --- a/spec/unit/puppet/type/firewalld_direct_passthrough_spec.rb +++ b/spec/unit/puppet/type/firewalld_direct_passthrough_spec.rb @@ -7,7 +7,7 @@ context 'with no params' do describe 'when validating attributes' do - %i[inet_protocol args].each do |param| + [:inet_protocol, :args].each do |param| it "should have a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:param) end @@ -55,16 +55,16 @@ context 'autorequires' do # rubocop:disable RSpec/InstanceVariable before do - @firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') + firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource(@firewalld_service) + @catalog.add_resource(firewalld_service) end it 'autorequires the firewalld service' do - @resource = described_class.new(name: '-A OUTPUT -j OUTPUT_filter') - @catalog.add_resource(@resource) + resource = described_class.new(name: '-A OUTPUT -j OUTPUT_filter') + @catalog.add_resource(resource) - expect(@resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') + expect(resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') end # rubocop:enable RSpec/InstanceVariable end diff --git a/spec/unit/puppet/type/firewalld_direct_rule_spec.rb b/spec/unit/puppet/type/firewalld_direct_rule_spec.rb index 39abe3e8..2e6df270 100644 --- a/spec/unit/puppet/type/firewalld_direct_rule_spec.rb +++ b/spec/unit/puppet/type/firewalld_direct_rule_spec.rb @@ -7,7 +7,7 @@ context 'with no params' do describe 'when validating attributes' do - %i[inet_protocol args table chain priority].each do |param| + [:inet_protocol, :args, :table, :chain, :priority].each do |param| it "should have a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:param) end @@ -82,9 +82,9 @@ context 'autorequires' do # rubocop:disable RSpec/InstanceVariable before do - @firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') + firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource(@firewalld_service) + @catalog.add_resource(firewalld_service) end let(:attrs) do @@ -99,10 +99,10 @@ end it 'autorequires the firewalld service' do - @resource = described_class.new(attrs) - @catalog.add_resource(@resource) + resource = described_class.new(attrs) + @catalog.add_resource(resource) - expect(@resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') + expect(resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') end # rubocop:enable RSpec/InstanceVariable end diff --git a/spec/unit/puppet/type/firewalld_ipset_spec.rb b/spec/unit/puppet/type/firewalld_ipset_spec.rb index 04dcc18f..84afdcc0 100644 --- a/spec/unit/puppet/type/firewalld_ipset_spec.rb +++ b/spec/unit/puppet/type/firewalld_ipset_spec.rb @@ -7,17 +7,13 @@ describe 'type' do describe 'when validating attributes' do - %i[ - name type options manage_entries - ].each do |param| + [:name, :type, :options, :manage_entries].each do |param| it "should have a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:param) end end - %i[ - entries family hashsize maxelem timeout - ].each do |prop| + [:entries, :family, :hashsize, :maxelem, :timeout].each do |prop| it "should have a #{prop} property" do expect(described_class.attrtype(prop)).to eq(:property) end @@ -159,16 +155,16 @@ context 'autorequires' do # rubocop:disable RSpec/InstanceVariable before do - @firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') + firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource(@firewalld_service) + @catalog.add_resource(firewalld_service) end it 'autorequires the firewalld service' do - @resource = described_class.new(name: 'test', hashsize: 128) - @catalog.add_resource(@resource) + resource = described_class.new(name: 'test', hashsize: 128) + @catalog.add_resource(resource) - expect(@resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') + expect(resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') end # rubocop:enable RSpec/InstanceVariable end diff --git a/spec/unit/puppet/type/firewalld_port_spec.rb b/spec/unit/puppet/type/firewalld_port_spec.rb index 4886a37e..7eaf1545 100644 --- a/spec/unit/puppet/type/firewalld_port_spec.rb +++ b/spec/unit/puppet/type/firewalld_port_spec.rb @@ -7,7 +7,7 @@ context 'with no params' do describe 'when validating attributes' do - %i[name zone port protocol].each do |param| + [:name, :zone, :port, :protocol].each do |param| it "should have a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:param) end @@ -24,16 +24,16 @@ context 'autorequires' do # rubocop:disable RSpec/InstanceVariable before do - @firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') + firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource(@firewalld_service) + @catalog.add_resource(firewalld_service) end it 'autorequires the firewalld service' do - @resource = described_class.new(name: 'test', port: 1234) - @catalog.add_resource(@resource) + resource = described_class.new(name: 'test', port: 1234) + @catalog.add_resource(resource) - expect(@resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') + expect(resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') end # rubocop:enable RSpec/InstanceVariable end diff --git a/spec/unit/puppet/type/firewalld_rich_rule_spec.rb b/spec/unit/puppet/type/firewalld_rich_rule_spec.rb index 8dffc543..160c8167 100644 --- a/spec/unit/puppet/type/firewalld_rich_rule_spec.rb +++ b/spec/unit/puppet/type/firewalld_rich_rule_spec.rb @@ -6,20 +6,20 @@ end context 'with no params' do describe 'when validating attributes' do - %i[ - family - zone - source - service - action - protocol - icmp_block - masquerade - forward_port - log - audit - action - raw_rule + [ + :family, + :zone, + :source, + :service, + :action, + :protocol, + :icmp_block, + :masquerade, + :forward_port, + :log, + :audit, + :action, + :raw_rule ].each do |param| it "should have a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:param) @@ -208,9 +208,9 @@ context 'autorequires' do # rubocop:disable RSpec/InstanceVariable before do - @firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') + firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource(@firewalld_service) + @catalog.add_resource(firewalld_service) end let(:attrs) do @@ -226,10 +226,10 @@ end it 'autorequires the firewalld service' do - @resource = described_class.new(attrs) - @catalog.add_resource(@resource) + resource = described_class.new(attrs) + @catalog.add_resource(resource) - expect(@resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') + expect(resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') end # rubocop:enable RSpec/InstanceVariable end diff --git a/spec/unit/puppet/type/firewalld_service_spec.rb b/spec/unit/puppet/type/firewalld_service_spec.rb index 162f9104..5dd0a53f 100644 --- a/spec/unit/puppet/type/firewalld_service_spec.rb +++ b/spec/unit/puppet/type/firewalld_service_spec.rb @@ -7,7 +7,7 @@ context 'with no params' do describe 'when validating attributes' do - %i[name service zone].each do |param| + [:name, :service, :zone].each do |param| it "should have a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:param) end @@ -24,16 +24,16 @@ context 'autorequires' do # rubocop:disable RSpec/InstanceVariable before do - @firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') + firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource(@firewalld_service) + @catalog.add_resource(firewalld_service) end it 'autorequires the firewalld service' do - @resource = described_class.new(name: 'test', service: 'test') - @catalog.add_resource(@resource) + resource = described_class.new(name: 'test', service: 'test') + @catalog.add_resource(resource) - expect(@resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') + expect(resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') end # rubocop:enable RSpec/InstanceVariable end diff --git a/spec/unit/puppet/type/firewalld_zone_spec.rb b/spec/unit/puppet/type/firewalld_zone_spec.rb index 1251442c..8ad4ba15 100644 --- a/spec/unit/puppet/type/firewalld_zone_spec.rb +++ b/spec/unit/puppet/type/firewalld_zone_spec.rb @@ -16,9 +16,7 @@ end end - %i[ - target icmp_blocks sources purge_rich_rules purge_services purge_ports - ].each do |param| + [:target, :icmp_blocks, :sources, :purge_rich_rules, :purge_services, :purge_ports].each do |param| it "should have a #{param} parameter" do expect(described_class.attrtype(param)).to eq(:property) end @@ -165,16 +163,16 @@ context 'autorequires' do # rubocop:disable RSpec/InstanceVariable before do - @firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') + firewalld_service = Puppet::Type.type(:service).new(name: 'firewalld') @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource(@firewalld_service) + @catalog.add_resource(firewalld_service) end it 'autorequires the firewalld service' do - @resource = described_class.new(name: 'test') - @catalog.add_resource(@resource) + resource = described_class.new(name: 'test') + @catalog.add_resource(resource) - expect(@resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') + expect(resource.autorequire.map { |rp| rp.source.to_s }).to include('Service[firewalld]') end # rubocop:enable RSpec/InstanceVariable end