Skip to content

Commit 3fa7900

Browse files
committed
feat(apache::vhost): refactor ModSecurity configuration handling
- Add modsec_rule_engine parameter (Enum['On','Off','DetectionOnly'], default 'On') to explicitly control SecRuleEngine directive - Deprecate modsec_disable_vhost boolean in favor of modsec_rule_engine (retain backward compatibility via deprecation warning) - Security fragment template is now always included (as before) - Add EPP signature with explicit type enforcement to _security.epp - Guard all non-engine directives in _security.epp behind modsec_rule_engine != 'Off' to prevent inert configuration noise when ModSecurity is disabled
1 parent 7197649 commit 3fa7900

3 files changed

Lines changed: 74 additions & 53 deletions

File tree

manifests/mod/security.pp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@
145145
Boolean $custom_rules = $apache::params::modsec_custom_rules,
146146
Optional[Array[String]] $custom_rules_set = $apache::params::modsec_custom_rules_set,
147147
Stdlib::Absolutepath $modsec_dir = $apache::params::modsec_dir,
148-
String $modsec_secruleengine = $apache::params::modsec_secruleengine,
149-
Integer[0, 9] $debug_log_level = 0,
148+
Enum['On', 'Off', 'DetectionOnly'] $modsec_secruleengine = $apache::params::modsec_secruleengine,
149+
Integer[0, 9] $debug_log_level = 0,
150150
String $audit_log_relevant_status = '^(?:5|4(?!04))',
151151
String $audit_log_parts = $apache::params::modsec_audit_log_parts,
152152
String $audit_log_type = $apache::params::modsec_audit_log_type,

manifests/vhost.pp

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,6 +1710,10 @@
17101710
#
17111711
# @param proxy_protocol_exceptions
17121712
# Disable processing of PROXY header for certain hosts or networks
1713+
#
1714+
# @param modsec_rule_engine
1715+
# Configures the rules engine.
1716+
#
17131717
define apache::vhost (
17141718
Variant[Stdlib::Absolutepath, Boolean] $docroot,
17151719
Boolean $manage_docroot = true,
@@ -1973,6 +1977,7 @@
19731977
Optional[Variant[String[1], Array[String[1]]]] $userdir = undef,
19741978
Optional[Boolean] $proxy_protocol = undef,
19751979
Array[Stdlib::Host] $proxy_protocol_exceptions = [],
1980+
Optional[Enum['On', 'Off', 'DetectionOnly']] $modsec_rule_engine = undef,
19761981
) {
19771982
# The base class must be included first because it is used by parameter defaults
19781983
if ! defined(Class['apache']) {
@@ -2181,28 +2186,19 @@
21812186
}
21822187

21832188
## Create a global LocationMatch if locations aren't defined
2184-
if $modsec_disable_ids {
2185-
if $modsec_disable_ids =~ Array {
2186-
$_modsec_disable_ids = { '.*' => $modsec_disable_ids }
2187-
} else {
2188-
$_modsec_disable_ids = $modsec_disable_ids
2189-
}
2189+
$_modsec_disable_ids = $modsec_disable_ids ? {
2190+
Array => { '.*' => $modsec_disable_ids },
2191+
default => $modsec_disable_ids,
21902192
}
21912193

2192-
if $modsec_disable_msgs {
2193-
if $modsec_disable_msgs =~ Array {
2194-
$_modsec_disable_msgs = { '.*' => $modsec_disable_msgs }
2195-
} else {
2196-
$_modsec_disable_msgs = $modsec_disable_msgs
2197-
}
2194+
$_modsec_disable_msgs = $modsec_disable_msgs ? {
2195+
Array => { '.*' => $modsec_disable_msgs },
2196+
default => $modsec_disable_msgs,
21982197
}
21992198

2200-
if $modsec_disable_tags {
2201-
if $modsec_disable_tags =~ Array {
2202-
$_modsec_disable_tags = { '.*' => $modsec_disable_tags }
2203-
} else {
2204-
$_modsec_disable_tags = $modsec_disable_tags
2205-
}
2199+
$_modsec_disable_tags = $modsec_disable_tags ? {
2200+
Array => { '.*' => $modsec_disable_tags },
2201+
default => $modsec_disable_tags,
22062202
}
22072203

22082204
concat { "${priority_real}${filename}.conf":
@@ -2840,19 +2836,33 @@
28402836
}
28412837
}
28422838

2843-
if $modsec_disable_vhost or $modsec_disable_ids or !empty($modsec_disable_ips) or $modsec_disable_msgs or $modsec_disable_tags or $modsec_audit_log_destination or ($modsec_inbound_anomaly_threshold and $modsec_outbound_anomaly_threshold) or $modsec_allowed_methods {
2844-
$security_params = {
2845-
'modsec_disable_vhost' => $modsec_disable_vhost,
2846-
'modsec_audit_log_destination' => $modsec_audit_log_destination,
2847-
'_modsec_disable_ids' => $modsec_disable_ids,
2848-
'modsec_disable_ips' => $modsec_disable_ips,
2849-
'_modsec_disable_msgs' => $modsec_disable_msgs,
2850-
'_modsec_disable_tags' => $modsec_disable_tags,
2851-
'modsec_body_limit' => $modsec_body_limit,
2852-
'modsec_inbound_anomaly_threshold' => $modsec_inbound_anomaly_threshold,
2853-
'modsec_outbound_anomaly_threshold' => $modsec_outbound_anomaly_threshold,
2854-
'modsec_allowed_methods' => $modsec_allowed_methods,
2855-
}
2839+
if $modsec_disable_vhost and $modsec_rule_engine == undef {
2840+
warning('modsec_disable_vhost is deprecated, use modsec_rule_engine => Off instead')
2841+
}
2842+
2843+
$_modsec_rule_engine = $modsec_rule_engine ? {
2844+
undef => $modsec_disable_vhost ? {
2845+
true => 'Off',
2846+
default => 'On',
2847+
},
2848+
default => $modsec_rule_engine,
2849+
}
2850+
2851+
$modsec_enabled = ($modsec_rule_engine != undef or $modsec_disable_vhost or $modsec_audit_log_destination != undef or $modsec_disable_ids != undef or !empty($modsec_disable_ips) or $modsec_disable_msgs != undef or $modsec_disable_tags != undef or $modsec_body_limit != undef or $modsec_inbound_anomaly_threshold != undef or $modsec_outbound_anomaly_threshold != undef or $modsec_allowed_methods != undef)
2852+
2853+
$security_params = {
2854+
'_modsec_rule_engine' => $_modsec_rule_engine,
2855+
'modsec_audit_log_destination' => $modsec_audit_log_destination,
2856+
'_modsec_disable_ids' => $_modsec_disable_ids,
2857+
'modsec_disable_ips' => $modsec_disable_ips,
2858+
'_modsec_disable_msgs' => $_modsec_disable_msgs,
2859+
'_modsec_disable_tags' => $_modsec_disable_tags,
2860+
'modsec_body_limit' => $modsec_body_limit,
2861+
'modsec_inbound_anomaly_threshold' => $modsec_inbound_anomaly_threshold,
2862+
'modsec_outbound_anomaly_threshold' => $modsec_outbound_anomaly_threshold,
2863+
'modsec_allowed_methods' => $modsec_allowed_methods,
2864+
}
2865+
if $modsec_enabled {
28562866
concat::fragment { "${name}-security":
28572867
target => "${priority_real}${filename}.conf",
28582868
order => 320,

templates/vhost/_security.epp

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,65 @@
1+
<%- | Enum['On', 'Off', 'DetectionOnly'] $_modsec_rule_engine,
2+
Optional[String] $modsec_audit_log_destination,
3+
Optional[Hash] $_modsec_disable_ids,
4+
Array[String] $modsec_disable_ips,
5+
Optional[Hash] $_modsec_disable_msgs,
6+
Optional[Hash] $_modsec_disable_tags,
7+
Optional[String] $modsec_body_limit,
8+
Optional[Integer] $modsec_inbound_anomaly_threshold,
9+
Optional[Integer] $modsec_outbound_anomaly_threshold,
10+
Optional[String] $modsec_allowed_methods,
11+
| -%>
112
<IfModule mod_security2.c>
2-
<% if $modsec_disable_vhost {-%>
3-
SecRuleEngine Off
4-
<% } -%>
5-
<% if $modsec_audit_log_destination {-%>
13+
SecRuleEngine <%= $_modsec_rule_engine %>
14+
<% if $_modsec_rule_engine != 'Off' { -%>
15+
<% if $modsec_audit_log_destination { -%>
616
SecAuditLog "<%= $modsec_audit_log_destination %>"
717
<% } -%>
8-
<% if $_modsec_disable_ids =~ Hash {-%>
9-
<% $_modsec_disable_ids.each |$location, $rules| {-%>
18+
<% if $_modsec_disable_ids =~ Hash and !$_modsec_disable_ids.empty { -%>
19+
<% $_modsec_disable_ids.each |$location, $rules| { -%>
1020
<LocationMatch <%= $location %>>
11-
<% Array($rules).each |$rule| {-%>
21+
<% Array($rules).each |$rule| { -%>
1222
SecRuleRemoveById <%= $rule %>
1323
<% } -%>
1424
</LocationMatch>
1525
<% } -%>
1626
<% } -%>
17-
<% unless $modsec_disable_ips.empty {%>
27+
<% unless $modsec_disable_ips.empty { -%>
1828
SecRule REMOTE_ADDR "<%= join($modsec_disable_ips, ',') %>" "nolog,allow,id:1234123455"
19-
SecAction "phase:2,pass,nolog,id:1234123456"
29+
SecAction "phase:2,pass,nolog,id:1234123456"
2030
<% } -%>
21-
<% if $_modsec_disable_msgs =~ Hash {-%>
22-
<% $_modsec_disable_msgs.each |$location, $rules| {-%>
31+
<% if $_modsec_disable_msgs =~ Hash and !$_modsec_disable_msgs.empty { -%>
32+
<% $_modsec_disable_msgs.each |$location, $rules| { -%>
2333
<LocationMatch <%= $location %>>
24-
<% Array($rules).each |$rule| {-%>
34+
<% Array($rules).each |$rule| { -%>
2535
SecRuleRemoveByMsg "<%= $rule %>"
2636
<% } -%>
2737
</LocationMatch>
2838
<% } -%>
2939
<% } -%>
30-
<% if $_modsec_disable_tags =~ Hash {-%>
31-
<% $_modsec_disable_tags.each |$location, $rules| {-%>
40+
<% if $_modsec_disable_tags =~ Hash and !$_modsec_disable_tags.empty { -%>
41+
<% $_modsec_disable_tags.each |$location, $rules| { -%>
3242
<LocationMatch <%= $location %>>
33-
<% Array($rules).each |$rule| {-%>
43+
<% Array($rules).each |$rule| { -%>
3444
SecRuleRemoveByTag "<%= $rule %>"
3545
<% } -%>
3646
</LocationMatch>
3747
<% } -%>
3848
<% } -%>
39-
<% if $modsec_body_limit {-%>
49+
<% if $modsec_body_limit { -%>
4050
SecRequestBodyLimit <%= $modsec_body_limit %>
4151
<% } -%>
42-
<% if $modsec_inbound_anomaly_threshold and $modsec_outbound_anomaly_threshold {-%>
52+
<% if $modsec_inbound_anomaly_threshold and $modsec_outbound_anomaly_threshold { -%>
4353
SecAction \
4454
"id:900110,\
4555
phase:1,\
4656
nolog,\
4757
pass,\
4858
t:none,\
49-
setvar:tx.inbound_anomaly_score_threshold=<%= $modsec_inbound_anomaly_threshold -%>, \
50-
setvar:tx.outbound_anomaly_score_threshold=<%= $modsec_outbound_anomaly_threshold -%>"
59+
setvar:tx.inbound_anomaly_score_threshold=<%= $modsec_inbound_anomaly_threshold %>,\
60+
setvar:tx.outbound_anomaly_score_threshold=<%= $modsec_outbound_anomaly_threshold %>"
5161
<% } -%>
52-
<% if $modsec_allowed_methods {-%>
62+
<% if $modsec_allowed_methods { -%>
5363
SecAction \
5464
"id:900200,\
5565
phase:1,\
@@ -58,4 +68,5 @@
5868
t:none,\
5969
setvar:'tx.allowed_methods=<%= $modsec_allowed_methods -%>'"
6070
<% } -%>
71+
<% } -%>
6172
</IfModule>

0 commit comments

Comments
 (0)