diff --git a/REFERENCE.md b/REFERENCE.md index 76106a38a..d4d18cd99 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -6070,6 +6070,7 @@ The following parameters are available in the `apache::mod::security` class: * [`activated_rules`](#-apache--mod--security--activated_rules) * [`custom_rules`](#-apache--mod--security--custom_rules) * [`custom_rules_set`](#-apache--mod--security--custom_rules_set) +* [`custom_actions_set`](#-apache--mod--security--custom_actions_set) * [`modsec_dir`](#-apache--mod--security--modsec_dir) * [`modsec_secruleengine`](#-apache--mod--security--modsec_secruleengine) * [`debug_log_level`](#-apache--mod--security--debug_log_level) @@ -6151,10 +6152,18 @@ Default value: `$apache::params::modsec_custom_rules` Data type: `Optional[Array[String]]` - +Custom `SecRule` rules to be included Default value: `$apache::params::modsec_custom_rules_set` +##### `custom_actions_set` + +Data type: `Optional[Array[String]]` + +Custom `SecAction` rules to be included + +Default value: `undef` + ##### `modsec_dir` Data type: `Stdlib::Absolutepath` diff --git a/manifests/mod/security.pp b/manifests/mod/security.pp index 27de2e8a4..4af17c93c 100644 --- a/manifests/mod/security.pp +++ b/manifests/mod/security.pp @@ -16,7 +16,9 @@ # @param custom_rules # # @param custom_rules_set -# +# Custom `SecRule` rules to be included +# @param custom_actions_set +# Custom `SecAction` rules to be included # @param modsec_dir # Defines the path where Puppet installs the modsec configuration and activated rules links. # @@ -144,6 +146,7 @@ Array[String] $activated_rules = $apache::params::modsec_default_rules, Boolean $custom_rules = $apache::params::modsec_custom_rules, Optional[Array[String]] $custom_rules_set = $apache::params::modsec_custom_rules_set, + Optional[Array[String]] $custom_actions_set = undef, Stdlib::Absolutepath $modsec_dir = $apache::params::modsec_dir, String $modsec_secruleengine = $apache::params::modsec_secruleengine, Integer[0, 9] $debug_log_level = 0, @@ -319,7 +322,7 @@ owner => $apache::params::user, group => $apache::params::group, mode => $apache::file_mode, - content => epp('apache/mod/security_custom.conf.epp', { 'custom_rules_set' => $custom_rules_set, }), + content => epp('apache/mod/security_custom.conf.epp', { 'custom_rules_set' => $custom_rules_set, 'custom_actions_set' => $custom_actions_set, }), require => File["${modsec_dir}/custom_rules"], notify => Class['apache::service'], } @@ -373,7 +376,7 @@ notify => Class['apache::service'], } - unless $facts['os']['name'] == 'SLES' or $facts['os']['name'] == 'Debian' or $facts['os']['name'] == 'Ubuntu' { + unless $facts['os']['name'] == 'SLES' { apache::security::rule_link { $activated_rules: } } } diff --git a/manifests/params.pp b/manifests/params.pp index 60318ef6a..d8287eaaa 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -486,25 +486,25 @@ $secpcrematchlimitrecursion = 1500 $modsec_secruleengine = 'On' $modsec_default_rules = [ - 'crawlers-user-agents.data', - 'iis-errors.data', - 'java-code-leakages.data', - 'java-errors.data', - 'lfi-os-files.data', - 'php-config-directives.data', - 'php-errors.data', - 'php-function-names-933150.data', - 'php-function-names-933151.data', - 'php-variables.data', - 'restricted-files.data', - 'scanners-headers.data', - 'scanners-urls.data', - 'scanners-user-agents.data', - 'scripting-user-agents.data', - 'sql-errors.data', - 'sql-function-names.data', - 'unix-shell.data', - 'windows-powershell-commands.data', + 'rules/crawlers-user-agents.data', + 'rules/iis-errors.data', + 'rules/java-code-leakages.data', + 'rules/java-errors.data', + 'rules/lfi-os-files.data', + 'rules/php-config-directives.data', + 'rules/php-errors.data', + 'rules/php-function-names-933150.data', + 'rules/php-function-names-933151.data', + 'rules/php-variables.data', + 'rules/restricted-files.data', + 'rules/scanners-headers.data', + 'rules/scanners-urls.data', + 'rules/scanners-user-agents.data', + 'rules/scripting-user-agents.data', + 'rules/sql-errors.data', + 'rules/sql-function-names.data', + 'rules/unix-shell.data', + 'rules/windows-powershell-commands.data', ] $alias_icons_path = '/usr/share/apache2/icons' $error_documents_path = '/usr/share/apache2/error' diff --git a/spec/classes/mod/security_spec.rb b/spec/classes/mod/security_spec.rb index 126377767..6aef2efea 100644 --- a/spec/classes/mod/security_spec.rb +++ b/spec/classes/mod/security_spec.rb @@ -155,7 +155,7 @@ } end - describe 'with parameters' do + describe 'with custom rules' do let :params do { custom_rules: true, @@ -173,6 +173,24 @@ it { is_expected.to contain_file('/etc/httpd/modsecurity.d/custom_rules/custom_01_rules.conf').with_content %r{^\s*.*"id:199999,phase:1,nolog,allow,ctl:ruleEngine=off"$} } end + describe 'with custom actions' do + let :params do + { + custom_rules: true, + custom_actions_set: ['id:199999,phase:1,pass,nolog,t:none,initcol:global=global'] + } + end + + it { + expect(subject).to contain_file('/etc/httpd/modsecurity.d/custom_rules').with( + ensure: 'directory', path: '/etc/httpd/modsecurity.d/custom_rules', + owner: 'apache', group: 'apache' + ) + } + + it { is_expected.to contain_file('/etc/httpd/modsecurity.d/custom_rules/custom_01_rules.conf').with_content %r{^\s*.*"id:199999,phase:1,pass,nolog,t:none,initcol:global=global"$} } + end + describe 'with CRS parameters' do let :params do { @@ -284,6 +302,15 @@ ) } + it { is_expected.to contain_apache__security__rule_link('rules/crawlers-user-agents.data') } + + it { + expect(subject).to contain_file('crawlers-user-agents.data').with( + path: '/etc/modsecurity/activated_rules/crawlers-user-agents.data', + target: '/usr/share/modsecurity-crs/rules/crawlers-user-agents.data', + ) + } + it { expect(subject).to contain_file('/etc/modsecurity/security_crs.conf').with( path: '/etc/modsecurity/security_crs.conf', @@ -302,7 +329,7 @@ } end - describe 'with parameters' do + describe 'with custom rules' do let :params do { custom_rules: true, @@ -320,6 +347,56 @@ it { is_expected.to contain_file('/etc/modsecurity/custom_rules/custom_01_rules.conf').with_content %r{\s*.*"id:199999,phase:1,nolog,allow,ctl:ruleEngine=off"$} } end + describe 'with custom actions' do + let :params do + { + custom_rules: true, + custom_actions_set: ['id:199999,phase:1,pass,nolog,t:none,initcol:global=global'] + } + end + + it { + expect(subject).to contain_file('/etc/modsecurity/custom_rules').with( + ensure: 'directory', path: '/etc/modsecurity/custom_rules', + owner: 'www-data', group: 'www-data' + ) + } + + it { is_expected.to contain_file('/etc/modsecurity/custom_rules/custom_01_rules.conf').with_content %r{\s*.*"id:199999,phase:1,pass,nolog,t:none,initcol:global=global"$} } + end + + describe 'with absolute path to activated rule' do + let :params do + { + activated_rules: ['/tmp/foo/bar.conf'] + } + end + + it { is_expected.to contain_apache__security__rule_link('/tmp/foo/bar.conf') } + + it { + expect(subject).to contain_file('bar.conf').with( + path: '/etc/modsecurity/activated_rules/bar.conf', + target: '/tmp/foo/bar.conf', + ) + } + end + describe 'with relative path to activated rule' do + let :params do + { + activated_rules: ['rules/bar.conf'] + } + end + + it { is_expected.to contain_apache__security__rule_link('rules/bar.conf') } + it { + expect(subject).to contain_file('bar.conf').with( + path: '/etc/modsecurity/activated_rules/bar.conf', + target: '/usr/share/modsecurity-crs/rules/bar.conf', + ) + } + end + describe 'with mod security version' do let :params do { diff --git a/templates/mod/security_custom.conf.epp b/templates/mod/security_custom.conf.epp index e2570c44a..4c3ff6ace 100644 --- a/templates/mod/security_custom.conf.epp +++ b/templates/mod/security_custom.conf.epp @@ -1,6 +1,12 @@ # This file is managed by puppet, any direct modification will be overwritten. +<% if $custom_actions_set and !($custom_actions_set.empty) { -%> +<% $custom_actions_set.each |$secaction| { -%> +SecAction "<%= $secaction %>" +<% } -%> +<% } -%> + <% if $custom_rules_set and !($custom_rules_set.empty) { -%> <% $custom_rules_set.each |$secrule| { -%> SecRule <%= $secrule %> <% } -%> -<% } -%> \ No newline at end of file +<% } -%>