diff --git a/pfSense-pkg-API/files/etc/inc/api/models/DNSResolverAccessList.inc b/pfSense-pkg-API/files/etc/inc/api/models/DNSResolverAccessList.inc index 33c6f5566..47772b3c7 100644 --- a/pfSense-pkg-API/files/etc/inc/api/models/DNSResolverAccessList.inc +++ b/pfSense-pkg-API/files/etc/inc/api/models/DNSResolverAccessList.inc @@ -4,6 +4,7 @@ namespace API\Models; use API\Core\Auth; use API\Core\Model; +use API\Dispatchers\DNSResolverApplyDispatcher; use API\Fields\NestedModelField; use API\Fields\StringField; diff --git a/pfSense-pkg-API/files/etc/inc/api/models/DNSResolverAccessListNetwork.inc b/pfSense-pkg-API/files/etc/inc/api/models/DNSResolverAccessListNetwork.inc index 1e3d64aaf..531c38fe9 100644 --- a/pfSense-pkg-API/files/etc/inc/api/models/DNSResolverAccessListNetwork.inc +++ b/pfSense-pkg-API/files/etc/inc/api/models/DNSResolverAccessListNetwork.inc @@ -4,6 +4,7 @@ namespace API\Models; use API\Core\Auth; use API\Core\Model; +use API\Dispatchers\DNSResolverApplyDispatcher; use API\Fields\IntegerField; use API\Fields\StringField; use API\Responses\ValidationError; diff --git a/pfSense-pkg-API/files/etc/inc/api/tests/APIModelsDNSResolverAccessListNetworkTestCase.inc b/pfSense-pkg-API/files/etc/inc/api/tests/APIModelsDNSResolverAccessListNetworkTestCase.inc new file mode 100644 index 000000000..e190d6066 --- /dev/null +++ b/pfSense-pkg-API/files/etc/inc/api/tests/APIModelsDNSResolverAccessListNetworkTestCase.inc @@ -0,0 +1,95 @@ + "test", + "action" => "allow snoop", + "networks" => [ + ["network" => "1.2.3.4", "mask" => 32] + ] + ], + async: false + ); + $access_list->create(apply: true); + + # Create an access list network to test with + $access_list_network = new DNSResolverAccessListNetwork( + parent_id: $access_list->id, + data: ["network" => "4.3.2.1", "mask" => 24], + async: false + ); + $access_list_network->create(apply: true); + + # Ensure the access list exists in /var/unbound/access_lists.conf + $unbound_acls = file_get_contents("/var/unbound/access_lists.conf"); + $this->assert_is_true( + str_contains( + $unbound_acls, + "#test\naccess-control: 1.2.3.4/32 allow_snoop\naccess-control: 4.3.2.1/24 allow_snoop" + ) + ); + + # Update the access list network with new values + $access_list_network->from_representation(["network" => "127.0.0.5", "mask" => 29]); + $access_list_network->update(apply: true); + + # Ensure the new access list exists and the previous one doesn't + $unbound_acls = file_get_contents("/var/unbound/access_lists.conf"); + $this->assert_is_false( + str_contains( + $unbound_acls, + "#test\naccess-control: 1.2.3.4/32 allow_snoop\naccess-control: 4.3.2.1/24 allow_snoop" + ) + ); + $this->assert_is_true( + str_contains( + $unbound_acls, + "#test\naccess-control: 1.2.3.4/32 allow_snoop\naccess-control: 127.0.0.5/29 allow_snoop" + ) + ); + + # Delete the access list and ensure it no longer exists + $access_list_network->delete(apply: true); + $unbound_acls = file_get_contents("/var/unbound/access_lists.conf"); + $this->assert_is_false( + str_contains( + $unbound_acls, + "#test\naccess-control: 1.2.3.4/32 allow_snoop\naccess-control: 127.0.0.5/29 allow_snoop" + ) + ); + + # Delete the parent access list + $access_list->delete(apply: true); + } + + /** + * Checks that IPv4 network entries cannot use a `mask` greater than `32` + */ + public function test_validate_mask() { + # Try to create an IPv4 access list network entry with a mask greater than 32 + $access_list_network = new DNSResolverAccessListNetwork( + data: ["network" => "4.3.2.1", "mask" => 33], + async: false + ); + $this->assert_throws_response( + response_id: "DNS_RESOLVER_ACCESS_LIST_NETWORK_MASK_EXCEEDS_MAXIMUM_IPV4", + code: 400, + callable: function () use ($access_list_network) { + $access_list_network->validate(skip_parent: true); + } + ); + } +} \ No newline at end of file diff --git a/pfSense-pkg-API/files/etc/inc/api/tests/APIModelsDNSResolverAccessListTestCase.inc b/pfSense-pkg-API/files/etc/inc/api/tests/APIModelsDNSResolverAccessListTestCase.inc new file mode 100644 index 000000000..3cb0b0d11 --- /dev/null +++ b/pfSense-pkg-API/files/etc/inc/api/tests/APIModelsDNSResolverAccessListTestCase.inc @@ -0,0 +1,75 @@ + "test", + "action" => "allow", + "networks" => [ + ["network" => "1.2.3.4", "mask" => 32], + ["network" => "4.3.2.1", "mask" => 24], + ] + ], + async: false + ); + $access_list->create(apply: true); + + # Ensure the access list exists in /var/unbound/access_lists.conf + $unbound_acls = file_get_contents("/var/unbound/access_lists.conf"); + $this->assert_is_true( + str_contains( + $unbound_acls, + "#test\naccess-control: 1.2.3.4/32 allow\naccess-control: 4.3.2.1/24 allow" + ) + ); + + # Update the access list with new values + $access_list->from_representation( + [ + "name" => "updated-test", + "action" => "deny", + "networks" => [ + ["network" => "127.0.0.5", "mask" => 29], + ["network" => "127.0.0.1", "mask" => 25], + ] + ] + ); + $access_list->update(apply: true); + + # Ensure the new access list exists and the previous one doesn't + $unbound_acls = file_get_contents("/var/unbound/access_lists.conf"); + $this->assert_is_false( + str_contains( + $unbound_acls, + "#test\naccess-control: 1.2.3.4/32 allow\naccess-control: 4.3.2.1/24 allow" + ) + ); + $this->assert_is_true( + str_contains( + $unbound_acls, + "#updated-test\naccess-control: 127.0.0.5/29 deny\naccess-control: 127.0.0.1/25 deny" + ) + ); + + # Delete the access list and ensure it no longer exists + $access_list->delete(apply: true); + $unbound_acls = file_get_contents("/var/unbound/access_lists.conf"); + $this->assert_is_false( + str_contains( + $unbound_acls, + "#updated-test\naccess-control: 127.0.0.5/29 deny\naccess-control: 127.0.0.1/25 deny" + ) + ); + } +} \ No newline at end of file