From 1e8c8d601916f7aefe510c1e3dedf5dacc1b0d04 Mon Sep 17 00:00:00 2001 From: Junade Ali Date: Tue, 19 Sep 2017 16:04:35 +0100 Subject: [PATCH] COM-40 :: Add ZoneLockdown and UA Rules --- README.md | 10 +- src/Configurations/Configurations.php | 15 ++ src/Configurations/UARules.php | 29 +++ src/Configurations/ZoneLockdown.php | 38 +++ src/Endpoints/UARules.php | 124 ++++++++++ src/Endpoints/ZoneLockdown.php | 124 ++++++++++ .../ConfigurationsUARulesTest.php | 25 ++ tests/Configurations/ZoneLockdownTest.php | 34 +++ tests/Endpoints/UARulesTest.php | 218 +++++++++++++++++ tests/Endpoints/ZoneLockdownTest.php | 228 ++++++++++++++++++ 10 files changed, 840 insertions(+), 5 deletions(-) create mode 100644 src/Configurations/Configurations.php create mode 100644 src/Configurations/UARules.php create mode 100644 src/Configurations/ZoneLockdown.php create mode 100644 src/Endpoints/UARules.php create mode 100644 src/Endpoints/ZoneLockdown.php create mode 100644 tests/Configurations/ConfigurationsUARulesTest.php create mode 100644 tests/Configurations/ZoneLockdownTest.php create mode 100644 tests/Endpoints/UARulesTest.php create mode 100644 tests/Endpoints/ZoneLockdownTest.php diff --git a/README.md b/README.md index ac24a55..03c6241 100644 --- a/README.md +++ b/README.md @@ -12,15 +12,15 @@ The Cloudflare API can be found [here](https://api.cloudflare.com/). Each API call is provided via a similarly named function within various classes in the **Cloudflare\API\Endpoints** namespace: -- [x] DNS Records +- [x] [DNS Records](https://www.cloudflare.com/dns/) - [x] Zones - [x] User Administration (partial) -- [x] Cloudflare IPs -- [ ] Page Rules -- [ ] Web Application Firewall (WAF) +- [x] [Cloudflare IPs](https://www.cloudflare.com/ips/) +- [ ] [Page Rules](https://support.cloudflare.com/hc/en-us/articles/200168306-Is-there-a-tutorial-for-Page-Rules-) +- [ ] [Web Application Firewall (WAF)](https://www.cloudflare.com/waf/) - [ ] Virtual DNS Management - [ ] Custom hostnames -- [ ] Zone Lockdown and User-Agent Block rules +- [x] Zone Lockdown and User-Agent Block rules - [ ] Organization Administration - [ ] [Railgun](https://www.cloudflare.com/railgun/) administration - [ ] [Keyless SSL](https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/) diff --git a/src/Configurations/Configurations.php b/src/Configurations/Configurations.php new file mode 100644 index 0000000..bdcbdb2 --- /dev/null +++ b/src/Configurations/Configurations.php @@ -0,0 +1,15 @@ +target = "ua"; + $object->value = $value; + + array_push($this->configs, $object); + } + + public function getArray(): array + { + return $this->configs; + } +} \ No newline at end of file diff --git a/src/Configurations/ZoneLockdown.php b/src/Configurations/ZoneLockdown.php new file mode 100644 index 0000000..c4d6da3 --- /dev/null +++ b/src/Configurations/ZoneLockdown.php @@ -0,0 +1,38 @@ +target = "ip"; + $object->value = $value; + + array_push($this->configs, $object); + } + + public function addIPRange(string $value) + { + $object = new \stdClass(); + $object->target = "ip_range"; + $object->value = $value; + + array_push($this->configs, $object); + } + + public function getArray(): array + { + return $this->configs; + } +} \ No newline at end of file diff --git a/src/Endpoints/UARules.php b/src/Endpoints/UARules.php new file mode 100644 index 0000000..7c9010d --- /dev/null +++ b/src/Endpoints/UARules.php @@ -0,0 +1,124 @@ +adapter = $adapter; + } + + public function listRules( + string $zoneID, + int $page = 1, + int $perPage = 20 + ): \stdClass { + $options = [ + 'page' => $page, + 'per_page' => $perPage + ]; + + $query = http_build_query($options); + + $user = $this->adapter->get('zones/' . $zoneID . '/firewall/ua_rules?' . $query, []); + $body = json_decode($user->getBody()); + + $result = new \stdClass(); + $result->result = $body->result; + $result->result_info = $body->result_info; + + return $result; + } + + public function createRule( + string $zoneID, + string $mode, + \Cloudflare\API\Configurations\Configurations $configuration, + string $id = null, + string $description = null + ): bool { + + $options = [ + 'mode' => $mode, + 'configurations' => $configuration->getArray() + ]; + + if ($id !== null) { + $options['id'] = $id; + } + + if ($description !== null) { + $options['description'] = $description; + } + + $user = $this->adapter->post('zones/' . $zoneID . '/firewall/ua_rules', [], $options); + + $body = json_decode($user->getBody()); + + if (isset($body->result->id)) { + return true; + } + + return false; + } + + public function getRuleDetails(string $zoneID, string $blockID): \stdClass + { + $user = $this->adapter->get('zones/' . $zoneID . '/firewall/ua_rules/' . $blockID, []); + $body = json_decode($user->getBody()); + return $body->result; + } + + public function updateRule( + string $zoneID, + string $ruleID, + string $mode, + \Cloudflare\API\Configurations\UARules $configuration, + string $description = null + ): bool { + + $options = [ + 'mode' => $mode, + 'id' => $ruleID, + 'configurations' => $configuration->getArray() + ]; + + if ($description !== null) { + $options['description'] = $description; + } + + $user = $this->adapter->put('zones/' . $zoneID . '/firewall/ua_rules/' . $ruleID, [], $options); + + $body = json_decode($user->getBody()); + + if (isset($body->result->id)) { + return true; + } + + return false; + } + + public function deleteRule(string $zoneID, string $ruleID): bool + { + $user = $this->adapter->delete('zones/' . $zoneID . '/firewall/ua_rules/' . $ruleID, [], []); + + $body = json_decode($user->getBody()); + + if (isset($body->result->id)) { + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/Endpoints/ZoneLockdown.php b/src/Endpoints/ZoneLockdown.php new file mode 100644 index 0000000..5f4b5d9 --- /dev/null +++ b/src/Endpoints/ZoneLockdown.php @@ -0,0 +1,124 @@ +adapter = $adapter; + } + + public function listLockdowns( + string $zoneID, + int $page = 1, + int $perPage = 20 + ): \stdClass { + $options = [ + 'page' => $page, + 'per_page' => $perPage + ]; + + $query = http_build_query($options); + + $user = $this->adapter->get('zones/' . $zoneID . '/firewall/lockdowns?' . $query, []); + $body = json_decode($user->getBody()); + + $result = new \stdClass(); + $result->result = $body->result; + $result->result_info = $body->result_info; + + return $result; + } + + public function createLockdown( + string $zoneID, + array $urls, + \Cloudflare\API\Configurations\ZoneLockdown $configuration, + string $id = null, + string $description = null + ): bool { + + $options = [ + 'urls' => $urls, + 'configurations' => $configuration->getArray() + ]; + + if ($id !== null) { + $options['id'] = $id; + } + + if ($description !== null) { + $options['description'] = $description; + } + + $user = $this->adapter->post('zones/' . $zoneID . '/firewall/lockdowns', [], $options); + + $body = json_decode($user->getBody()); + + if (isset($body->result->id)) { + return true; + } + + return false; + } + + public function getLockdownDetails(string $zoneID, string $lockdownID): \stdClass + { + $user = $this->adapter->get('zones/' . $zoneID . '/firewall/lockdowns/' . $lockdownID, []); + $body = json_decode($user->getBody()); + return $body->result; + } + + public function updateLockdown( + string $zoneID, + string $lockdownID, + array $urls, + \Cloudflare\API\Configurations\ZoneLockdown $configuration, + string $description = null + ): bool { + + $options = [ + 'urls' => $urls, + 'id' => $lockdownID, + 'configurations' => $configuration->getArray() + ]; + + if ($description !== null) { + $options['description'] = $description; + } + + $user = $this->adapter->put('zones/' . $zoneID . '/firewall/lockdowns/' . $lockdownID, [], $options); + + $body = json_decode($user->getBody()); + + if (isset($body->result->id)) { + return true; + } + + return false; + } + + public function deleteLockdown(string $zoneID, string $lockdownID): bool + { + $user = $this->adapter->delete('zones/' . $zoneID . '/firewall/lockdowns/' . $lockdownID, [], []); + + $body = json_decode($user->getBody()); + + if (isset($body->result->id)) { + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/tests/Configurations/ConfigurationsUARulesTest.php b/tests/Configurations/ConfigurationsUARulesTest.php new file mode 100644 index 0000000..2ee461e --- /dev/null +++ b/tests/Configurations/ConfigurationsUARulesTest.php @@ -0,0 +1,25 @@ +addUA('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4'); + + $array = $configuration->getArray(); + $this->assertEquals(1, sizeof($array)); + + $this->assertObjectHasAttribute('target', $array[0]); + $this->assertEquals('ua', $array[0]->target); + $this->assertObjectHasAttribute('value', $array[0]); + $this->assertEquals('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4', + $array[0]->value); + } +} diff --git a/tests/Configurations/ZoneLockdownTest.php b/tests/Configurations/ZoneLockdownTest.php new file mode 100644 index 0000000..af1a2ad --- /dev/null +++ b/tests/Configurations/ZoneLockdownTest.php @@ -0,0 +1,34 @@ +addIP('1.2.3.4'); + + $array = $configuration->getArray(); + $this->assertEquals(1, sizeof($array)); + + $this->assertObjectHasAttribute('target', $array[0]); + $this->assertEquals('ip', $array[0]->target); + $this->assertObjectHasAttribute('value', $array[0]); + $this->assertEquals('1.2.3.4', $array[0]->value); + + $configuration->addIPRange('1.2.3.4/24'); + + $array = $configuration->getArray(); + $this->assertEquals(2, sizeof($array)); + + $this->assertObjectHasAttribute('target', $array[1]); + $this->assertEquals('ip_range', $array[1]->target); + $this->assertObjectHasAttribute('value', $array[1]); + $this->assertEquals('1.2.3.4/24', $array[1]->value); + } +} diff --git a/tests/Endpoints/UARulesTest.php b/tests/Endpoints/UARulesTest.php new file mode 100644 index 0000000..a2d573d --- /dev/null +++ b/tests/Endpoints/UARulesTest.php @@ -0,0 +1,218 @@ + 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('get')->willReturn($response); + + $mock->expects($this->once()) + ->method('get') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/ua_rules?page=1&per_page=20'), + $this->equalTo([]) + ); + + $zones = new \Cloudflare\API\Endpoints\UARules($mock); + $result = $zones->listRules("023e105f4ecef8ad9ca31a8372d0c353", 1, 20); + + $this->assertObjectHasAttribute('result', $result); + $this->assertObjectHasAttribute('result_info', $result); + + $this->assertEquals("372e67954025e0ba6aaa6d586b9e0b59", $result->result[0]->id); + $this->assertEquals(1, $result->result_info->page); + } + + public function testCreateRule() + { + $config = new \Cloudflare\API\Configurations\UARules(); + $config->addUA('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4'); + + $stream = GuzzleHttp\Psr7\stream_for(' +{ + "success": true, + "errors": [ + {} + ], + "messages": [ + {} + ], + "result": { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "description": "Prevent access from abusive clients identified by this UserAgent to mitigate DDoS attack", + "mode": "js_challenge", + "configuration": { + "target": "ua", + "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4" + } + } +}'); + $response = new GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('post')->willReturn($response); + + $mock->expects($this->once()) + ->method('post') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/ua_rules'), $this->equalTo([]), + $this->equalTo([ + 'mode' => 'js_challenge', + 'id' => '372e67954025e0ba6aaa6d586b9e0b59', + 'description' => 'Prevent access from abusive clients identified by this UserAgent to mitigate DDoS attack', + 'configurations' => $config->getArray(), + ]) + ); + + $ld = new \Cloudflare\API\Endpoints\UARules($mock); + $ld->createRule('023e105f4ecef8ad9ca31a8372d0c353', 'js_challenge', $config, + '372e67954025e0ba6aaa6d586b9e0b59', + 'Prevent access from abusive clients identified by this UserAgent to mitigate DDoS attack'); + } + + public function getRuleDetails() + { + $stream = GuzzleHttp\Psr7\stream_for('{ + "success": true, + "errors": [ + {} + ], + "messages": [ + {} + ], + "result": { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "description": "Prevent access from abusive clients identified by this UserAgent to mitigate DDoS attack", + "mode": "js_challenge", + "configuration": { + "target": "ua", + "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4" + } + } +}'); + + $response = new GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('get')->willReturn($response); + + $mock->expects($this->once()) + ->method('get') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/ua_rules/372e67954025e0ba6aaa6d586b9e0b59'), + $this->equalTo([]) + ); + + $lockdown = new \Cloudflare\API\Endpoints\UARules($mock); + $result = $lockdown->getRuleDetails("023e105f4ecef8ad9ca31a8372d0c353", "372e67954025e0ba6aaa6d586b9e0b59"); + + $this->assertEquals("372e67954025e0ba6aaa6d586b9e0b59", $result->id); + } + + public function testUpdateRule() + { + $config = new \Cloudflare\API\Configurations\UARules(); + $config->addUA('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4'); + + $stream = GuzzleHttp\Psr7\stream_for(' +{ + "success": true, + "errors": [ + {} + ], + "messages": [ + {} + ], + "result": { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "description": "Prevent access from abusive clients identified by this UserAgent to mitigate DDoS attack", + "mode": "js_challenge", + "configuration": { + "target": "ua", + "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4" + } + } +}'); + $response = new GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('put')->willReturn($response); + + $mock->expects($this->once()) + ->method('put') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/ua_rules/372e67954025e0ba6aaa6d586b9e0b59'), + $this->equalTo([]), + $this->equalTo([ + 'mode' => 'js_challenge', + 'id' => '372e67954025e0ba6aaa6d586b9e0b59', + 'description' => 'Restrict access to these endpoints to requests from a known IP address', + 'configurations' => $config->getArray(), + ]) + ); + + $ld = new \Cloudflare\API\Endpoints\UARules($mock); + $ld->updateRule('023e105f4ecef8ad9ca31a8372d0c353', '372e67954025e0ba6aaa6d586b9e0b59', + 'js_challenge', $config, + 'Restrict access to these endpoints to requests from a known IP address'); + } + + public function testDeleteRule() + { + $stream = GuzzleHttp\Psr7\stream_for('{ + "success": true, + "errors": [ + {} + ], + "messages": [ + {} + ], + "result": { + "id": "372e67954025e0ba6aaa6d586b9e0b59" + } +}'); + $response = new GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('delete')->willReturn($response); + + $mock->expects($this->once()) + ->method('delete') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/ua_rules/372e67954025e0ba6aaa6d586b9e0b59'), + $this->equalTo([]), + $this->equalTo([]) + ); + + $ld = new \Cloudflare\API\Endpoints\UARules($mock); + $ld->deleteRule('023e105f4ecef8ad9ca31a8372d0c353', '372e67954025e0ba6aaa6d586b9e0b59'); + } +} diff --git a/tests/Endpoints/ZoneLockdownTest.php b/tests/Endpoints/ZoneLockdownTest.php new file mode 100644 index 0000000..9f2ce8f --- /dev/null +++ b/tests/Endpoints/ZoneLockdownTest.php @@ -0,0 +1,228 @@ + 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('get')->willReturn($response); + + $mock->expects($this->once()) + ->method('get') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/lockdowns?page=1&per_page=20'), + $this->equalTo([]) + ); + + $zones = new \Cloudflare\API\Endpoints\ZoneLockdown($mock); + $result = $zones->listLockdowns("023e105f4ecef8ad9ca31a8372d0c353", 1, 20); + + $this->assertObjectHasAttribute('result', $result); + $this->assertObjectHasAttribute('result_info', $result); + + $this->assertEquals("372e67954025e0ba6aaa6d586b9e0b59", $result->result[0]->id); + $this->assertEquals(1, $result->result_info->page); + } + + public function testAddLockdown() + { + $config = new \Cloudflare\API\Configurations\ZoneLockdown(); + $config->addIP('1.2.3.4'); + + $stream = GuzzleHttp\Psr7\stream_for(' +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "description": "Restrict access to these endpoints to requests from a known IP address", + "urls": [ + "api.mysite.com/some/endpoint*" + ], + "configurations": [ + { + "target": "ip", + "value": "1.2.3.4" + } + ] + } +}'); + $response = new GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('post')->willReturn($response); + + $mock->expects($this->once()) + ->method('post') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/lockdowns'), $this->equalTo([]), + $this->equalTo([ + 'urls' => ["api.mysite.com/some/endpoint*"], + 'id' => '372e67954025e0ba6aaa6d586b9e0b59', + 'description' => 'Restrict access to these endpoints to requests from a known IP address', + 'configurations' => $config->getArray(), + ]) + ); + + $ld = new \Cloudflare\API\Endpoints\ZoneLockdown($mock); + $ld->createLockdown('023e105f4ecef8ad9ca31a8372d0c353', ["api.mysite.com/some/endpoint*"], $config, + '372e67954025e0ba6aaa6d586b9e0b59', + 'Restrict access to these endpoints to requests from a known IP address'); + } + + public function testGetRecordDetails() + { + $stream = GuzzleHttp\Psr7\stream_for('{ + "success": true, + "errors": [ + {} + ], + "messages": [ + {} + ], + "result": { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "description": "Restrict access to these endpoints to requests from a known IP address", + "urls": [ + "api.mysite.com/some/endpoint*" + ], + "configurations": [ + { + "target": "ip", + "value": "1.2.3.4" + } + ] + } +}'); + + $response = new GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('get')->willReturn($response); + + $mock->expects($this->once()) + ->method('get') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/lockdowns/372e67954025e0ba6aaa6d586b9e0b59'), + $this->equalTo([]) + ); + + $lockdown = new \Cloudflare\API\Endpoints\ZoneLockdown($mock); + $result = $lockdown->getLockdownDetails("023e105f4ecef8ad9ca31a8372d0c353", "372e67954025e0ba6aaa6d586b9e0b59"); + + $this->assertEquals("372e67954025e0ba6aaa6d586b9e0b59", $result->id); + } + + public function testUpdateLockdown() + { + $config = new \Cloudflare\API\Configurations\ZoneLockdown(); + $config->addIP('1.2.3.4'); + + $stream = GuzzleHttp\Psr7\stream_for(' +{ + "success": true, + "errors": [ + {} + ], + "messages": [ + {} + ], + "result": { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "description": "Restrict access to these endpoints to requests from a known IP address", + "urls": [ + "api.mysite.com/some/endpoint*" + ], + "configurations": [ + { + "target": "ip", + "value": "1.2.3.4" + } + ] + } +}'); + $response = new GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('put')->willReturn($response); + + $mock->expects($this->once()) + ->method('put') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/lockdowns/372e67954025e0ba6aaa6d586b9e0b59'), + $this->equalTo([]), + $this->equalTo([ + 'urls' => ["api.mysite.com/some/endpoint*"], + 'id' => '372e67954025e0ba6aaa6d586b9e0b59', + 'description' => 'Restrict access to these endpoints to requests from a known IP address', + 'configurations' => $config->getArray(), + ]) + ); + + $ld = new \Cloudflare\API\Endpoints\ZoneLockdown($mock); + $ld->updateLockdown('023e105f4ecef8ad9ca31a8372d0c353', '372e67954025e0ba6aaa6d586b9e0b59', + ["api.mysite.com/some/endpoint*"], $config, + 'Restrict access to these endpoints to requests from a known IP address'); + } + + public function testDeleteLockdown() + { + $config = new \Cloudflare\API\Configurations\ZoneLockdown(); + $config->addIP('1.2.3.4'); + + $stream = GuzzleHttp\Psr7\stream_for(' +{ + "success": true, + "errors": [ + {} + ], + "messages": [ + {} + ], + "result": { + "id": "372e67954025e0ba6aaa6d586b9e0b59" + } +}'); + $response = new GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json'], $stream); + $mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock(); + $mock->method('delete')->willReturn($response); + + $mock->expects($this->once()) + ->method('delete') + ->with($this->equalTo('zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/lockdowns/372e67954025e0ba6aaa6d586b9e0b59'), + $this->equalTo([]), + $this->equalTo([]) + ); + + $ld = new \Cloudflare\API\Endpoints\ZoneLockdown($mock); + $ld->deleteLockdown('023e105f4ecef8ad9ca31a8372d0c353', '372e67954025e0ba6aaa6d586b9e0b59'); + } +}