Imported Upstream version 2.5.11
[libapache-mod-security.git] / apache2 / t / regression / config / 10-audit-directives.t
1 ### SecAudit* directive tests
2
3 # SecAuditEngine
4 {
5         type => "config",
6         comment => "SecAuditEngine On",
7         conf => qq(
8                 SecAuditEngine On
9                 SecAuditLog $ENV{AUDIT_LOG}
10         ),
11         match_log => {
12                 audit => [ qr/./, 1 ],
13         },
14         match_response => {
15                 status => qr/^200$/,
16         },
17         request => new HTTP::Request(
18                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
19         ),
20 },
21 {
22         type => "config",
23         comment => "SecAuditEngine Off",
24         conf => qq(
25                 SecAuditEngine Off
26                 SecAuditLog $ENV{AUDIT_LOG}
27         ),
28         match_log => {
29                 -audit => [ qr/./, 1 ],
30         },
31         match_response => {
32                 status => qr/^200$/,
33         },
34         request => new HTTP::Request(
35                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
36         ),
37 },
38 {
39         type => "config",
40         comment => "SecAuditEngine RelevantOnly (pos)",
41         conf => qq(
42                 SecRuleEngine On
43                 SecAuditEngine RelevantOnly
44                 SecAuditLog $ENV{AUDIT_LOG}
45                 SecDebugLog $ENV{DEBUG_LOG}
46                 SecDebugLogLevel 9
47                 SecResponseBodyAccess On
48                 SecDefaultAction "phase:2,log,auditlog,pass"
49                 SecRule REQUEST_URI "." "phase:4,deny"
50         ),
51         match_log => {
52                 audit => [ qr/./, 1 ],
53         },
54         match_response => {
55                 status => qr/^403$/,
56         },
57         request => new HTTP::Request(
58                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
59         ),
60 },
61 {
62         type => "config",
63         comment => "SecAuditEngine RelevantOnly (neg)",
64         conf => qq(
65                 SecAuditEngine RelevantOnly
66                 SecAuditLog $ENV{AUDIT_LOG}
67                 SecResponseBodyAccess On
68                 SecDefaultAction "phase:2,log,auditlog,pass"
69         ),
70         match_log => {
71                 -audit => [ qr/./, 1 ],
72         },
73         match_response => {
74                 status => qr/^200$/,
75         },
76         request => new HTTP::Request(
77                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
78         ),
79 },
80
81 # SecAuditLogType & SecAuditLogStorageDir
82 {
83         type => "config",
84         comment => "SecAuditLogType Serial",
85         conf => qq(
86                 SecAuditEngine On
87                 SecAuditLog $ENV{AUDIT_LOG}
88                 SecAuditLogType Serial
89         ),
90         match_log => {
91                 audit => [ qr/./, 1 ],
92         },
93         match_response => {
94                 status => qr/^404$/,
95         },
96         request => new HTTP::Request(
97                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/bogus",
98         ),
99 },
100 {
101         type => "config",
102         comment => "SecAuditLogType Concurrent",
103         conf => qq(
104                 SecAuditEngine On
105                 SecAuditLog $ENV{AUDIT_LOG}
106                 SecAuditLogType Concurrent
107                 SecAuditLogStorageDir "$ENV{LOGS_DIR}/audit"
108         ),
109         test => sub {
110                 ### Perl code to parse the audit log entry and verify
111                 ### that the concurrent audit log exists and contains
112                 ### the correct data.
113                 ###
114                 ### TODO: Need some API for this :)
115                 ###
116
117                 # Parse log
118                 my $alogre = qr/^(?:\S+)\ (?:\S+)\ (?:\S+)\ (?:\S+)\ \[(?:[^:]+):(?:\d+:\d+:\d+)\ (?:[^\]]+)\]\ \"(?:.*)\"\ (?:\d+)\ (?:\S+)\ \"(?:.*)\"\ \"(?:.*)\"\ (\S+)\ \"(?:.*)\"\ (\S+)\ (?:\d+)\ (?:\d+)\ (?:\S+)(?:.*)$/m;
119                 my $alog = match_log("audit", $alogre, 1);
120                 chomp $alog;
121                 my @log = ($alog =~ m/$alogre/);
122                 my($id, $fn) = ($log[0], $log[1]);
123                 if (!$id or !$fn) {
124                         dbg("LOG ENTRY: $alog");
125                         die "Failed to parse audit log: $ENV{AUDIT_LOG}\n";
126                 }
127
128                 # Verify concurrent log exists
129                 my $alogdatafn = "$ENV{LOGS_DIR}/audit$fn";
130                 if (! -e "$alogdatafn") {
131                         die "Audit log does not exist: $alogdatafn\n";
132                 }
133
134                 # Verify concurrent log contents
135                 if (defined match_file($alogdatafn, qr/^--[^-]+-A--.*$id.*-Z--$/s)) {
136                         return 0;
137                 }
138
139                 # Error
140                 dbg("LOGDATA: \"$FILE{$alogdatafn}{buf}\"");
141                 die "Audit log data did not match.\n";
142         },
143         match_response => {
144                 status => qr/^200$/,
145         },
146         request => new HTTP::Request(
147                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
148         ),
149 },
150
151 # SecAuditLogRelevantStatus
152 {
153         type => "config",
154         comment => "SecAuditLogRelevantStatus (pos)",
155         conf => qq(
156                 SecAuditEngine RelevantOnly
157                 SecAuditLog $ENV{AUDIT_LOG}
158                 SecAuditLogRelevantStatus "^4"
159         ),
160         match_log => {
161                 audit => [ qr/./, 1 ],
162         },
163         match_response => {
164                 status => qr/^404$/,
165         },
166         request => new HTTP::Request(
167                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/bogus",
168         ),
169 },
170 {
171         type => "config",
172         comment => "SecAuditLogRelevantStatus (neg)",
173         conf => qq(
174                 SecAuditEngine RelevantOnly
175                 SecAuditLog $ENV{AUDIT_LOG}
176                 SecAuditLogRelevantStatus "^4"
177         ),
178         match_log => {
179                 -audit => [ qr/./, 1 ],
180         },
181         match_response => {
182                 status => qr/^200$/,
183         },
184         request => new HTTP::Request(
185                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
186         ),
187 },
188
189 # SecAuditLogParts
190 {
191         type => "config",
192         comment => "SecAuditLogParts (minimal)",
193         conf => qq(
194                 SecAuditEngine On
195                 SecAuditLog $ENV{AUDIT_LOG}
196                 SecRequestBodyAccess On
197                 SecResponseBodyAccess On
198                 SecAuditLogParts "AZ"
199         ),
200         match_log => {
201                 audit => [ qr/-A--.*-Z--/s, 1 ],
202                 -audit => [ qr/-[B-Y]--/, 1 ],
203         },
204         match_response => {
205                 status => qr/^200$/,
206         },
207         request => new HTTP::Request(
208                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
209                 [
210                         "Content-Type" => "application/x-www-form-urlencoded",
211                 ],
212                 "a=1r&=2",
213         ),
214 },
215 {
216         type => "config",
217         comment => "SecAuditLogParts (default)",
218         conf => qq(
219                 SecAuditEngine On
220                 SecAuditLog $ENV{AUDIT_LOG}
221                 SecRequestBodyAccess On
222                 SecResponseBodyAccess On
223         ),
224         match_log => {
225                 audit => [ qr/-A--.*-B--.*-F--.*-H--.*-Z--/s, 1 ],
226                 -audit => [ qr/-[DEGIJK]--/, 1 ],
227         },
228         match_response => {
229                 status => qr/^200$/,
230         },
231         request => new HTTP::Request(
232                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
233                 [
234                         "Content-Type" => "application/x-www-form-urlencoded",
235                 ],
236                 "a=1r&=2",
237         ),
238 },
239 {
240         type => "config",
241         comment => "SecAuditLogParts (all)",
242         conf => qq(
243                 SecRuleEngine On
244                 SecAuditEngine On
245                 SecAuditLog $ENV{AUDIT_LOG}
246                 SecRequestBodyAccess On
247                 SecResponseBodyAccess On
248                 SecAuditLogParts "ABCDEFGHIJKZ"
249                 SecAction "phase:4,log,auditlog,allow"
250         ),
251         match_log => {
252                 audit => [ qr/-A--.*-B--.*-C--.*-F--.*-E--.*-H--.*-K--.*-Z--/s, 1 ],
253         },
254         match_response => {
255                 status => qr/^200$/,
256         },
257         request => new HTTP::Request(
258                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
259                 [
260                         "Content-Type" => "application/x-www-form-urlencoded",
261                 ],
262                 "a=1r&=2",
263         ),
264 },