Skip to content

Commit 980c879

Browse files
committed
Pass secret from the options. Created firewall rule creation test.
1 parent 3f6f5e7 commit 980c879

2 files changed

Lines changed: 142 additions & 2 deletions

File tree

src/Processor.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ class Processor
6262
*/
6363
private $response;
6464

65+
/**
66+
* The secret that is used for the firewall rules integrity.
67+
* Default is set to "secret" for easy PHPUnit testing.
68+
*
69+
* @var string
70+
*/
71+
private $secret = 'secret';
72+
6573
/**
6674
* Creates a new processor instance.
6775
*
@@ -83,6 +91,8 @@ public function __construct(
8391
$this->whitelistRules = $whitelistRules;
8492
$this->options = array_merge($this->options, $options);
8593
$this->extension = $extension;
94+
95+
$this->secret = isset($options['secret']) ? $options['secret'] : 'secret';
8696
$this->request = new Request($this->options);
8797
$this->response = new Response($this->options);
8898
}
@@ -135,9 +145,9 @@ public function launch($mustExit = true)
135145
// Since the Opis/Closure package does not support PHP 8.1+, we have to use Laravel's ported version for 8.1+.
136146
require dirname(__FILE__) . '/../vendor/autoload.php';
137147
if (PHP_VERSION_ID < 80100) {
138-
\Opis\Closure\SerializableClosure::setSecretKey('secret');
148+
\Opis\Closure\SerializableClosure::setSecretKey($this->secret);
139149
} else {
140-
\Laravel\SerializableClosure\SerializableClosure::setSecretKey('secret');
150+
\Laravel\SerializableClosure\SerializableClosure::setSecretKey($this->secret);
141151
}
142152

143153
foreach ($this->firewallRules as $rule) {

tests/FirewallRuleCreationTest.php

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Patchstack\Processor;
7+
use Patchstack\Extensions\Test\Extension;
8+
9+
final class FirewallRuleCreationTest extends TestCase
10+
{
11+
/**
12+
* @var Processor
13+
*/
14+
protected $processor;
15+
16+
/**
17+
* @var array
18+
*/
19+
protected $rules;
20+
21+
/**
22+
* Setup the test for testing the header location redirect.
23+
*
24+
* @return void
25+
*/
26+
protected function setUp(): void
27+
{
28+
$this->rules = json_decode(file_get_contents(dirname(__FILE__) . '/data/Rules.json'));
29+
}
30+
31+
/**
32+
* Setup the firewall processor.
33+
*
34+
* @param array $rules
35+
* @return void
36+
*/
37+
private function setUpFirewallProcessor(array $rules)
38+
{
39+
$this->processor = new Processor(
40+
$rules,
41+
[],
42+
[],
43+
[],
44+
new Extension()
45+
);
46+
}
47+
48+
/**
49+
* Alters the payload between tests.
50+
* For most firewall rules there's no difference if testing against GET or POST.
51+
* Therefore, both can be used for testing payloads.
52+
*
53+
* @return void
54+
*/
55+
private function alterPayload(array $payload = [])
56+
{
57+
$_POST = [];
58+
$_GET = [];
59+
60+
$_POST = isset($payload['POST']) ? $payload['POST'] : [];
61+
$_GET = isset($payload['GET']) ? $payload['GET'] : [];
62+
}
63+
64+
/**
65+
* Test the creation of firewall rules.
66+
*
67+
* @return void
68+
*/
69+
public function testFirewallRuleCreation()
70+
{
71+
// Since the Opis/Closure package does not support PHP 8.1+, we have to use Laravel's ported version for 8.1+.
72+
require dirname(__FILE__) . '/../vendor/autoload.php';
73+
if (PHP_VERSION_ID < 80100) {
74+
\Opis\Closure\SerializableClosure::setSecretKey('secret');
75+
class_alias('\Opis\Closure\SerializableClosure', 'SerializeClosure');
76+
} else {
77+
\Laravel\SerializableClosure\SerializableClosure::setSecretKey('secret');
78+
class_alias('\Laravel\SerializableClosure\SerializableClosure', 'SerializeClosure');
79+
}
80+
81+
// Create the firewall rule.
82+
$function = function () {
83+
return isset($_GET['test']);
84+
};
85+
$wrapper = new SerializeClosure($function);
86+
$rule = (object) [
87+
'id' => 1,
88+
'title' => 'Block request with test query parameter in the URL.',
89+
'rule' => base64_encode(serialize($wrapper)),
90+
'cat' => 'TEST',
91+
'type' => 'BLOCK'
92+
];
93+
94+
// Test the rule.
95+
$this->setUpFirewallProcessor([$rule]);
96+
$this->alterPayload(
97+
['GET' => [
98+
'test' => 'yes'
99+
]]
100+
);
101+
$this->assertFalse($this->processor->launch(false));
102+
103+
// Create the more complex firewall rule.
104+
$function = function () {
105+
if (!isset($_POST['exec'])) {
106+
return false;
107+
}
108+
109+
$payload = json_decode(base64_decode($_POST['exec']), true);
110+
return $payload && isset($payload['user_role']) && $payload['user_role'] == 'administrator';
111+
};
112+
$wrapper = new SerializeClosure($function);
113+
$rule = (object) [
114+
'id' => 1,
115+
'title' => 'Block request with encoded payload',
116+
'rule' => base64_encode(serialize($wrapper)),
117+
'cat' => 'TEST',
118+
'type' => 'BLOCK'
119+
];
120+
121+
// Test the rule.
122+
$this->setUpFirewallProcessor([$rule]);
123+
$this->alterPayload(
124+
['POST' => [
125+
'exec' => base64_encode(json_encode(['user_role' => 'administrator']))
126+
]]
127+
);
128+
$this->assertFalse($this->processor->launch(false));
129+
}
130+
}

0 commit comments

Comments
 (0)