Skip to content

Commit d040fa6

Browse files
Merge pull request #924 from pfrest/next_minor
v2.9.0 Features & Fixes
2 parents 561f612 + 27e7fd9 commit d040fa6

16 files changed

Lines changed: 1048 additions & 19 deletions

‎pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Core/Endpoint.inc‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,13 @@ class Endpoint {
239239
*/
240240
public array $delete_privileges = [];
241241

242+
/**
243+
* @var bool $requires_page_all_privilege
244+
* When enabled, this endpoint will always require the page-all privilege and will
245+
* disable auto-generated/scoped REST API privileges for this endpoint.
246+
*/
247+
public bool $requires_page_all_privilege = false;
248+
242249
/**
243250
* @var string $get_help_text
244251
* Sets the GET request's OpenAPI documentation for this Endpoint. This will be
@@ -534,6 +541,17 @@ class Endpoint {
534541
*/
535542
private function get_default_privs(): void {
536543
$page_all_priv = 'page-all';
544+
545+
# If this endpoint requires page-all, then only assign page-all to the privileges for each method
546+
if ($this->requires_page_all_privilege) {
547+
$this->get_privileges = [$page_all_priv];
548+
$this->post_privileges = [$page_all_priv];
549+
$this->patch_privileges = [$page_all_priv];
550+
$this->put_privileges = [$page_all_priv];
551+
$this->delete_privileges = [$page_all_priv];
552+
return;
553+
}
554+
537555
$this->get_privileges = [$page_all_priv, $this->get_method_priv_name('GET')];
538556
$this->post_privileges = [$page_all_priv, $this->get_method_priv_name('POST')];
539557
$this->patch_privileges = [$page_all_priv, $this->get_method_priv_name('PATCH')];
@@ -564,6 +582,11 @@ class Endpoint {
564582
* @returns array The pfSense priv list entry array corresponding to the privileges of this Endpoint.
565583
*/
566584
public function generate_pfsense_privs(): array {
585+
# If this endpoint requires page-all, do not generate privileges
586+
if ($this->requires_page_all_privilege) {
587+
return [];
588+
}
589+
567590
# Set an array to populate pfSense priv entries for this Endpoint
568591
$privs = [];
569592

‎pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Core/Model.inc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1769,7 +1769,7 @@ class Model {
17691769
* @throws NotFoundError When the Model requires a pfSense package that is not installed.
17701770
* @throws ServerError When a package requires a PHP include file that could not be found.
17711771
*/
1772-
private function check_packages(): void {
1772+
protected function check_packages(): void {
17731773
# Check if the user has opted in to using development (-devel) package variants
17741774
$pkg_config = RESTAPI\Models\RESTAPISettings::get_pkg_config();
17751775
$allow_development_packages = ($pkg_config['allow_development_packages'] ?? '') === 'enabled';
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace RESTAPI\Endpoints;
4+
5+
require_once 'RESTAPI/autoloader.inc';
6+
7+
use RESTAPI\Core\Endpoint;
8+
9+
/**
10+
* Defines an Endpoint for interacting with multiple WireGuard peer status objects at /api/v2/status/wireguard/peers.
11+
*/
12+
class StatusWireGuardPeersEndpoint extends Endpoint {
13+
public function __construct() {
14+
# Set Endpoint attributes
15+
$this->url = '/api/v2/status/wireguard/peers';
16+
$this->model_name = 'WireGuardPeerStatus';
17+
$this->many = true;
18+
$this->request_method_options = ['GET'];
19+
20+
# Construct the parent Endpoint object
21+
parent::__construct();
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace RESTAPI\Endpoints;
4+
5+
require_once 'RESTAPI/autoloader.inc';
6+
7+
use RESTAPI\Core\Endpoint;
8+
9+
/**
10+
* Defines an Endpoint for interacting with multiple WireGuard tunnel status objects at /api/v2/status/wireguard/tunnels.
11+
*/
12+
class StatusWireGuardTunnelsEndpoint extends Endpoint {
13+
public function __construct() {
14+
# Set Endpoint attributes
15+
$this->url = '/api/v2/status/wireguard/tunnels';
16+
$this->model_name = 'WireGuardTunnelStatus';
17+
$this->many = true;
18+
$this->request_method_options = ['GET'];
19+
20+
# Construct the parent Endpoint object
21+
parent::__construct();
22+
}
23+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace RESTAPI\Endpoints;
4+
5+
require_once 'RESTAPI/autoloader.inc';
6+
7+
use RESTAPI\Core\Endpoint;
8+
9+
/**
10+
* Defines an Endpoint for interacting with pfSense High Availability synchronization settings.
11+
*/
12+
class SystemHASyncEndpoint extends Endpoint {
13+
public function __construct() {
14+
# Set Endpoint attributes
15+
$this->url = '/api/v2/system/hasync';
16+
$this->model_name = 'HASync';
17+
$this->request_method_options = ['GET', 'PATCH'];
18+
19+
$this->get_help_text = 'Reads pfSense High Availability synchronization settings.';
20+
$this->patch_help_text = 'Updates pfSense High Availability synchronization settings.';
21+
22+
parent::__construct();
23+
}
24+
}

‎pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Endpoints/SystemRESTAPISettingsSyncEndpoint.inc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class SystemRESTAPISettingsSyncEndpoint extends Endpoint {
2222
$this->ignore_interfaces = true;
2323
$this->ignore_read_only = true;
2424
$this->auth_methods = ['BasicAuth'];
25+
$this->requires_page_all_privilege = true;
2526

2627
# Construct the parent Endpoint object
2728
parent::__construct();
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
<?php
2+
3+
namespace RESTAPI\Models;
4+
5+
require_once 'RESTAPI/autoloader.inc';
6+
7+
use RESTAPI\Core\Model;
8+
use RESTAPI\Dispatchers\FirewallApplyDispatcher;
9+
use RESTAPI\Fields\BooleanField;
10+
use RESTAPI\Fields\InterfaceField;
11+
use RESTAPI\Fields\StringField;
12+
use RESTAPI\Validators\IPAddressValidator;
13+
14+
/**
15+
* Defines a Model for managing pfSense High Availability synchronization settings.
16+
*/
17+
class HASync extends Model {
18+
public StringField $synchronizetoip;
19+
public StringField $pfsyncpeerip;
20+
public InterfaceField $pfsyncinterface;
21+
public StringField $pfhostid;
22+
public StringField $username;
23+
public StringField $password;
24+
public BooleanField $pfsyncenabled;
25+
public BooleanField $adminsync;
26+
public BooleanField $synchronizeusers;
27+
public BooleanField $synchronizeauthservers;
28+
public BooleanField $synchronizecerts;
29+
public BooleanField $synchronizerules;
30+
public BooleanField $synchronizeschedules;
31+
public BooleanField $synchronizealiases;
32+
public BooleanField $synchronizenat;
33+
public BooleanField $synchronizeipsec;
34+
public BooleanField $synchronizeopenvpn;
35+
public BooleanField $synchronizedhcpd;
36+
public BooleanField $synchronizedhcpdv6;
37+
public BooleanField $synchronizekea6;
38+
public BooleanField $synchronizewol;
39+
public BooleanField $synchronizestaticroutes;
40+
public BooleanField $synchronizevirtualip;
41+
public BooleanField $synchronizetrafficshaper;
42+
public BooleanField $synchronizetrafficshaperlimiter;
43+
public BooleanField $synchronizednsforwarder;
44+
public BooleanField $synchronizecaptiveportal;
45+
public BooleanField $synchronizedhcrelay;
46+
public BooleanField $synchronizedhcrelay6;
47+
48+
public function __construct(mixed $id = null, mixed $parent_id = null, mixed $data = [], mixed ...$options) {
49+
# Set Model attributes
50+
$this->config_path = 'hasync';
51+
$this->many = false;
52+
$this->always_apply = true;
53+
$this->verbose_name = 'HA Sync Settings';
54+
$this->verbose_name_plural = 'HA Sync Settings';
55+
56+
$this->pfsyncenabled = new BooleanField(
57+
default: false,
58+
indicates_true: 'on',
59+
indicates_false: null,
60+
help_text: 'Enable pfsync state synchronization.',
61+
);
62+
$this->pfsyncinterface = new InterfaceField(
63+
default: 'lo0',
64+
allow_localhost_interface: true,
65+
allow_empty: true,
66+
help_text: 'The interface used by pfsync state synchronization.',
67+
);
68+
$this->pfhostid = new StringField(
69+
default: '',
70+
allow_empty: true,
71+
maximum_length: 8,
72+
help_text: 'Custom pf host identifier carried in state data.',
73+
);
74+
$this->pfsyncpeerip = new StringField(
75+
default: '',
76+
allow_empty: true,
77+
validators: [new IPAddressValidator(allow_ipv4: true, allow_ipv6: false)],
78+
help_text: 'The peer IP address used by pfsync.',
79+
);
80+
$this->synchronizetoip = new StringField(
81+
default: '',
82+
allow_empty: true,
83+
validators: [new IPAddressValidator(allow_ipv4: true, allow_ipv6: false)],
84+
help_text: 'The remote pfSense host IP address used for XMLRPC configuration synchronization.',
85+
);
86+
$this->username = new StringField(
87+
default: '',
88+
allow_empty: true,
89+
help_text: 'The remote pfSense username used for XMLRPC synchronization.',
90+
);
91+
$this->password = new StringField(
92+
default: '',
93+
allow_empty: true,
94+
write_only: true,
95+
sensitive: true,
96+
internal_name: 'passwordfld',
97+
help_text: 'The remote pfSense password used for XMLRPC synchronization.',
98+
);
99+
$this->adminsync = new BooleanField(
100+
default: false,
101+
indicates_true: 'on',
102+
indicates_false: null,
103+
help_text: 'Synchronize admin accounts and automatically update the XMLRPC sync password.',
104+
);
105+
$this->synchronizeusers = new BooleanField(
106+
default: false,
107+
indicates_true: 'on',
108+
indicates_false: null,
109+
help_text: 'Synchronize users and groups.',
110+
);
111+
$this->synchronizeauthservers = new BooleanField(
112+
default: false,
113+
indicates_true: 'on',
114+
indicates_false: null,
115+
help_text: 'Synchronize authentication servers.',
116+
);
117+
$this->synchronizecerts = new BooleanField(
118+
default: false,
119+
indicates_true: 'on',
120+
indicates_false: null,
121+
help_text: 'Synchronize certificates.',
122+
);
123+
$this->synchronizerules = new BooleanField(
124+
default: false,
125+
indicates_true: 'on',
126+
indicates_false: null,
127+
help_text: 'Synchronize firewall rules.',
128+
);
129+
$this->synchronizeschedules = new BooleanField(
130+
default: false,
131+
indicates_true: 'on',
132+
indicates_false: null,
133+
help_text: 'Synchronize firewall schedules.',
134+
);
135+
$this->synchronizealiases = new BooleanField(
136+
default: false,
137+
indicates_true: 'on',
138+
indicates_false: null,
139+
help_text: 'Synchronize firewall aliases.',
140+
);
141+
$this->synchronizenat = new BooleanField(
142+
default: false,
143+
indicates_true: 'on',
144+
indicates_false: null,
145+
help_text: 'Synchronize NAT configuration.',
146+
);
147+
$this->synchronizeipsec = new BooleanField(
148+
default: false,
149+
indicates_true: 'on',
150+
indicates_false: null,
151+
help_text: 'Synchronize IPsec configuration.',
152+
);
153+
$this->synchronizeopenvpn = new BooleanField(
154+
default: false,
155+
indicates_true: 'on',
156+
indicates_false: null,
157+
help_text: 'Synchronize OpenVPN configuration.',
158+
);
159+
$this->synchronizedhcpd = new BooleanField(
160+
default: false,
161+
indicates_true: 'on',
162+
indicates_false: null,
163+
help_text: 'Synchronize DHCP server configuration.',
164+
);
165+
$this->synchronizedhcpdv6 = new BooleanField(
166+
default: false,
167+
indicates_true: 'on',
168+
indicates_false: null,
169+
help_text: 'Synchronize DHCPv6 server configuration.',
170+
);
171+
$this->synchronizekea6 = new BooleanField(
172+
default: false,
173+
indicates_true: 'on',
174+
indicates_false: null,
175+
help_text: 'Synchronize Kea DHCPv6 server configuration.',
176+
);
177+
$this->synchronizedhcrelay = new BooleanField(
178+
default: false,
179+
indicates_true: 'on',
180+
indicates_false: null,
181+
help_text: 'Synchronize DHCP relay configuration.',
182+
);
183+
$this->synchronizedhcrelay6 = new BooleanField(
184+
default: false,
185+
indicates_true: 'on',
186+
indicates_false: null,
187+
help_text: 'Synchronize DHCPv6 relay configuration.',
188+
);
189+
$this->synchronizewol = new BooleanField(
190+
default: false,
191+
indicates_true: 'on',
192+
indicates_false: null,
193+
help_text: 'Synchronize Wake-on-LAN configuration.',
194+
);
195+
$this->synchronizestaticroutes = new BooleanField(
196+
default: false,
197+
indicates_true: 'on',
198+
indicates_false: null,
199+
help_text: 'Synchronize static routes.',
200+
);
201+
$this->synchronizevirtualip = new BooleanField(
202+
default: false,
203+
indicates_true: 'on',
204+
indicates_false: null,
205+
help_text: 'Synchronize virtual IP addresses.',
206+
);
207+
$this->synchronizetrafficshaper = new BooleanField(
208+
default: false,
209+
indicates_true: 'on',
210+
indicates_false: null,
211+
help_text: 'Synchronize traffic shaper queues.',
212+
);
213+
$this->synchronizetrafficshaperlimiter = new BooleanField(
214+
default: false,
215+
indicates_true: 'on',
216+
indicates_false: null,
217+
help_text: 'Synchronize traffic shaper limiters.',
218+
);
219+
$this->synchronizednsforwarder = new BooleanField(
220+
default: false,
221+
indicates_true: 'on',
222+
indicates_false: null,
223+
help_text: 'Synchronize DNS Forwarder and DNS Resolver configuration.',
224+
);
225+
$this->synchronizecaptiveportal = new BooleanField(
226+
default: false,
227+
indicates_true: 'on',
228+
indicates_false: null,
229+
help_text: 'Synchronize captive portal configuration.',
230+
);
231+
232+
parent::__construct($id, $parent_id, $data, ...$options);
233+
}
234+
235+
/**
236+
* Applies HA Sync configuration changes via the FirewallApplyDispatcher.
237+
*/
238+
public function apply(): void {
239+
(new FirewallApplyDispatcher(async: $this->async))->spawn_process();
240+
}
241+
}

‎pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/RESTAPISettings.inc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ class RESTAPISettings extends Model {
227227
allow_empty: true,
228228
verbose_name: 'HA username',
229229
help_text: "Sets the username to use when authenticating for HA sync processes. This user must be the present
230-
on all hosts defined in `ha_sync_hosts`.",
230+
on all hosts defined in `ha_sync_hosts` and must hold the `page-all` privilege",
231231
);
232232
$this->ha_sync_password = new StringField(
233233
default: '',

0 commit comments

Comments
 (0)