More tested regression tests.

Cleaned up script.
This commit is contained in:
brectanus
2008-05-30 00:13:50 +00:00
parent 043a5d6082
commit d06a3beab4
9 changed files with 677 additions and 82 deletions

View File

@@ -0,0 +1,248 @@
### Logging tests
# log/nolog
{
type => "action",
comment => "log",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,log"
),
match_log => {
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "action",
comment => "nolog",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,nolog"
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
# auditlog/noauditlog
{
type => "action",
comment => "auditlog",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,auditlog"
),
match_log => {
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ],
audit => [ qr/Message: Warning. Unconditional match in SecAction\./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "action",
comment => "noauditlog",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,noauditlog"
),
match_log => {
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ],
-audit => [ qr/./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
# All log/nolog auditlog/noauditlog combos
{
type => "action",
comment => "log,auditlog",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,log,auditlog"
),
match_log => {
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ],
audit => [ qr/Message: Warning. Unconditional match in SecAction\./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "action",
comment => "log,noauditlog",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,log,noauditlog"
),
match_log => {
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ],
-audit => [ qr/./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "action",
comment => "nolog,auditlog",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,nolog,auditlog"
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
# ENH: No message, but should have data. Is this intended?
audit => [ qr/-H--\s+Stopwatch: /s, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "action",
comment => "nolog,noauditlog",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,nolog,noauditlog"
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "action",
comment => "auditlog,log",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,auditlog,log"
),
match_log => {
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ],
audit => [ qr/Message: Warning. Unconditional match in SecAction\./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "action",
comment => "auditlog,nolog",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,auditlog,nolog"
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "action",
comment => "noauditlog,log",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,noauditlog,log"
),
match_log => {
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ],
-audit => [ qr/./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "action",
comment => "noauditlog,nolog",
conf => qq(
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog "$ENV{AUDIT_LOG}"
SecAction "phase:1,pass,noauditlog,nolog"
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},

View File

@@ -132,18 +132,12 @@
}
# Verify concurrent log contents
$LOG{$id}{fd} = new FileHandle($alogdatafn, O_RDONLY);
$LOG{$id}{fd}->blocking(0);
$LOG{$id}{buf} = "";
my $alogdata = match_log($id, qr/^--[^-]+-A--.*$id.*-Z--$/s, 1);
if (defined $alogdata) {
$LOG{$id}{fd}->close();
delete $LOG{$id};
if (defined match_file($alogdatafn, qr/^--[^-]+-A--.*$id.*-Z--$/s)) {
return 0;
}
# Error
dbg("LOGDATA: \"$alogdata\"");
dbg("LOGDATA: \"$FILE{$alogdatafn}{buf}\"");
die "Audit log data did not match.\n";
},
match_response => {

View File

@@ -2,13 +2,31 @@
### TODO:
# SecTmpDir
# SecUploadDir
# SecUploadKeepFiles
# SecWebAppId
# SecDataDir
# SecChrootDir
# SecGuardianLog
# SecDefaultAction
{
type => "config",
comment => "SecDefaultAction",
conf => qq(
SecRuleEngine on
SecDefaultAction "phase:1,deny,status:500"
SecRule REQUEST_URI "test.txt"
),
match_log => {
error => [ qr/ModSecurity: Access denied with code 500 \(phase 1\)/, 1 ],
},
match_response => {
status => qr/^500$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
# SecServerSignature
{
type => "config",
@@ -28,22 +46,78 @@
),
},
# SecDefaultAction
# SecDataDir
{
type => "config",
comment => "SecServerSignature On",
comment => "SecDataDir",
conf => qq(
SecRuleEngine on
SecDefaultAction "phase:1,deny,status:500"
SecRule REQUEST_URI "test.txt"
SecRuleEngine On
SecDataDir "$ENV{DATA_DIR}"
SecAction initcol:ip=%{REMOTE_ADDR},setvar:ip.dummy=1,pass
),
match_log => {
error => [ qr/ModSecurity: Access denied with code 500 \(phase 1\)/, 1 ],
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ],
},
match_file => {
"$ENV{DATA_DIR}/ip.pag" => qr/\x00\x06dummy\x00\x00\x021\x00/,
},
match_response => {
status => qr/^500$/,
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
# SecTmpDir/SecUploadDir/SecUploadKeepFiles
{
type => "config",
comment => "SecTmpDir/SecUploadDir/SecUploadKeepFiles",
conf => qq(
SecRuleEngine On
SecRequestBodyAccess On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 4
SecTmpDir "$ENV{TEMP_DIR}"
SecUploadKeepFiles On
SecUploadDir "$ENV{UPLOAD_DIR}"
),
test => sub {
# Get the filename and make sure the file exists
my $fn = match_log(debug => qr/Moved file from .* to ".*"\./, 5);
die "Failed to determine uploaded filename\n" unless (defined $fn);
$fn =~ s/Moved file from .* to "(.*)"\..*/$1/;
die "File does not exist: $fn\n" unless (-e $fn);
# Check the contents of the file
return 0 if (match_file($fn, qr/^TESTFILE$/m));
msg("Failed to match contents of uploaded file: $fn");
return 1;
},
match_log => {
debug => [ qr/Created temporary file: $ENV{TEMP_DIR}/, 1 ],
-debug => [ qr/Failed to /, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=---------------------------19813181771830765643996187206",
],
q(-----------------------------19813181771830765643996187206
Content-Disposition: form-data; name="upload-file"; filename="test"
Content-Type: application/octet-stream
TESTFILE
-----------------------------19813181771830765643996187206
Content-Disposition: form-data; name="file"
Upload File
-----------------------------19813181771830765643996187206--),
),
},

View File

@@ -0,0 +1,35 @@
### SecChroot tests
# TODO: Will not work as we need root access
#{
# type => "config",
# comment => "SecChroot",
# httpd_opts => qw(
# -DCHROOT
# ),
# conf => qq(
# # These will be in the chroot
# PidFile /logs/httpd.pid
# ScoreBoardFile /logs/httpd.scoreboard
# User nobody
# Group nogroup
#
# SecAuditEngine On
# SecDebugLog $ENV{DEBUG_LOG}
# SecDebugLogLevel 9
# SecAuditLog $ENV{AUDIT_LOG}
# SecAuditLogStorageDir "/logs/audit"
# SecAuditLogType Concurrent
# SecChrootDir "$ENV{TEST_SERVER_ROOT}"
# ),
# match_log => {
# debug => [ qr/./, 1 ],
# audit => [ qr/./, 1 ],
# },
# match_response => {
# status => qr/^200$/,
# },
# request => new HTTP::Request(
# GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
# ),
#},

View File

@@ -0,0 +1,24 @@
### Tests for basic rule components
# SecAction
{
type => "config",
comment => "SecAction (override default)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 4
SecAction "nolog"
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
debug => [ qr/Warning\. Unconditional match in SecAction\./, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},

View File

@@ -0,0 +1,4 @@
### Tests for rule inheritance
### TODO:
# SecRuleInheritance

View File

@@ -0,0 +1,129 @@
### Tests for rule exceptions
# SecRuleRemoveByMsg
# SecRuleRemoveById
{
type => "config",
comment => "SecRuleRemoveById (single)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:1"
SecRuleRemoveById 1
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
debug => [ qr/Starting phase REQUEST_HEADERS\..*This phase consists of 0 rule.*Starting phase RESPONSE_HEADERS\./s, 1 ],
-debug => [ qr/Access denied/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "config",
comment => "SecRuleRemoveById (multiple)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:1"
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:2"
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:3"
SecRuleRemoveById 1 2 3
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
debug => [ qr/Starting phase REQUEST_HEADERS\..*This phase consists of 0 rule.*Starting phase RESPONSE_HEADERS\./s, 1 ],
-debug => [ qr/Access denied/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "config",
comment => "SecRuleRemoveById (range)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:1"
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:2"
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:3"
SecRuleRemoveById 1-3
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
debug => [ qr/Starting phase REQUEST_HEADERS\..*This phase consists of 0 rule.*Starting phase RESPONSE_HEADERS\./s, 1 ],
-debug => [ qr/Access denied/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
{
type => "config",
comment => "SecRuleRemoveById (multiple + range)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:1"
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:2"
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:3"
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:4"
SecRuleRemoveById 1 2-4
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
debug => [ qr/Starting phase REQUEST_HEADERS\..*This phase consists of 0 rule.*Starting phase RESPONSE_HEADERS\./s, 1 ],
-debug => [ qr/Access denied/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},
# SecRuleRemoveByMsg
{
type => "config",
comment => "SecRuleRemoveByMsg",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRule REQUEST_URI "test" "phase:1,deny,status:500,id:1,msg:'testing rule'"
SecRuleRemoveByMsg "testing rule"
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
-audit => [ qr/./, 1 ],
debug => [ qr/Starting phase REQUEST_HEADERS\..*This phase consists of 0 rule.*Starting phase RESPONSE_HEADERS\./s, 1 ],
-debug => [ qr/Access denied/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
),
},

View File

@@ -1,8 +1,10 @@
### Base configuration for starting Apache httpd
# File locations
PidFile @MSC_REGRESSION_LOGS_DIR@/httpd.pid
ScoreBoardFile @MSC_REGRESSION_LOGS_DIR@/httpd.scoreboard
<IfDefine !CHROOT>
# File locations
PidFile @MSC_REGRESSION_LOGS_DIR@/httpd.pid
ScoreBoardFile @MSC_REGRESSION_LOGS_DIR@/httpd.scoreboard
</IfDefine>
<IfModule !mod_proxy.c>
LoadModule proxy_module modules/mod_proxy.so
@@ -24,9 +26,10 @@ ServerName localhost
LogLevel debug
ErrorLog @MSC_REGRESSION_LOGS_DIR@/error.log
DocumentRoot @MSC_REGRESSION_DOCROOT_DIR@
<Directory "@MSC_REGRESSION_DOCROOT_DIR@">
Options Indexes FollowSymLinks
AllowOverride None
</Directory>
<IfDefine !CHROOT>
DocumentRoot @MSC_REGRESSION_DOCROOT_DIR@
<Directory "@MSC_REGRESSION_DOCROOT_DIR@">
Options Indexes FollowSymLinks
AllowOverride None
</Directory>
</IfDefine>