Skip to content

Commit be9918b

Browse files
TechAsenasenchooo
andauthored
feat: Add System HA Sync endpoint (#901)
Co-authored-by: asenchooo <asenchooo@localhost.localdomain>
1 parent 092802b commit be9918b

2 files changed

Lines changed: 193 additions & 0 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
$this->tag = 'System';
19+
20+
$this->get_help_text = 'Reads pfSense High Availability synchronization settings.';
21+
$this->patch_help_text = 'Updates pfSense High Availability synchronization settings and applies the configuration.';
22+
23+
parent::__construct();
24+
}
25+
}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<?php
2+
3+
namespace RESTAPI\Models;
4+
5+
require_once 'RESTAPI/autoloader.inc';
6+
require_once 'filter.inc';
7+
8+
use RESTAPI\Core\Model;
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+
25+
public BooleanField $pfsyncenabled;
26+
public BooleanField $adminsync;
27+
28+
public BooleanField $synchronizeusers;
29+
public BooleanField $synchronizeauthservers;
30+
public BooleanField $synchronizecerts;
31+
public BooleanField $synchronizerules;
32+
public BooleanField $synchronizeschedules;
33+
public BooleanField $synchronizealiases;
34+
public BooleanField $synchronizenat;
35+
public BooleanField $synchronizeipsec;
36+
public BooleanField $synchronizeopenvpn;
37+
public BooleanField $synchronizedhcpd;
38+
public BooleanField $synchronizedhcpdv6;
39+
public BooleanField $synchronizekea6;
40+
public BooleanField $synchronizewol;
41+
public BooleanField $synchronizestaticroutes;
42+
public BooleanField $synchronizevirtualip;
43+
public BooleanField $synchronizetrafficshaper;
44+
public BooleanField $synchronizetrafficshaperlimiter;
45+
public BooleanField $synchronizednsforwarder;
46+
public BooleanField $synchronizecaptiveportal;
47+
public BooleanField $synchronizedhcrelay;
48+
public BooleanField $synchronizedhcrelay6;
49+
50+
public function __construct(mixed $id = null, mixed $parent_id = null, mixed $data = [], mixed ...$options) {
51+
# Set Model attributes
52+
$this->config_path = 'hasync';
53+
$this->many = false;
54+
$this->always_apply = true;
55+
$this->verbose_name = 'HA Sync Settings';
56+
$this->verbose_name_plural = 'HA Sync Settings';
57+
58+
# State Synchronization Settings (pfsync)
59+
$this->pfsyncenabled = $this->sync_flag('Enable pfsync state synchronization.');
60+
61+
$this->pfsyncinterface = new InterfaceField(
62+
default: '',
63+
allow_empty: true,
64+
help_text: 'The interface used by pfsync state synchronization.',
65+
);
66+
67+
$this->pfhostid = new StringField(
68+
default: '',
69+
allow_empty: true,
70+
maximum_length: 8,
71+
help_text: 'Custom pf host identifier carried in state data.',
72+
);
73+
74+
$this->pfsyncpeerip = new StringField(
75+
default: '',
76+
allow_empty: true,
77+
validators: [
78+
new IPAddressValidator(
79+
allow_ipv4: true,
80+
allow_ipv6: false,
81+
),
82+
],
83+
help_text: 'The peer IP address used by pfsync.',
84+
);
85+
86+
# Configuration Synchronization Settings (XMLRPC Sync)
87+
$this->synchronizetoip = new StringField(
88+
default: '',
89+
allow_empty: true,
90+
validators: [
91+
new IPAddressValidator(
92+
allow_ipv4: true,
93+
allow_ipv6: false,
94+
),
95+
],
96+
help_text: 'The remote pfSense host IP address used for XMLRPC configuration synchronization.',
97+
);
98+
99+
$this->username = new StringField(
100+
default: '',
101+
allow_empty: true,
102+
help_text: 'The remote pfSense username used for XMLRPC synchronization.',
103+
);
104+
105+
# pfSense stores the XMLRPC password in config.xml as <passwordfld>.
106+
# The API exposes it as "password" but writes it internally as "passwordfld".
107+
$this->password = new StringField(
108+
default: '',
109+
allow_empty: true,
110+
write_only: true,
111+
sensitive: true,
112+
internal_name: 'passwordfld',
113+
help_text: 'The remote pfSense password used for XMLRPC synchronization.',
114+
);
115+
116+
$this->adminsync = $this->sync_flag(
117+
'Synchronize admin accounts and automatically update the XMLRPC sync password.',
118+
);
119+
120+
# Select options to sync
121+
$this->synchronizeusers = $this->sync_flag('Synchronize users and groups.');
122+
$this->synchronizeauthservers = $this->sync_flag('Synchronize authentication servers.');
123+
$this->synchronizecerts = $this->sync_flag('Synchronize certificates.');
124+
$this->synchronizerules = $this->sync_flag('Synchronize firewall rules.');
125+
$this->synchronizeschedules = $this->sync_flag('Synchronize firewall schedules.');
126+
$this->synchronizealiases = $this->sync_flag('Synchronize firewall aliases.');
127+
$this->synchronizenat = $this->sync_flag('Synchronize NAT configuration.');
128+
$this->synchronizeipsec = $this->sync_flag('Synchronize IPsec configuration.');
129+
$this->synchronizeopenvpn = $this->sync_flag('Synchronize OpenVPN configuration.');
130+
$this->synchronizedhcpd = $this->sync_flag('Synchronize DHCP server configuration.');
131+
$this->synchronizedhcpdv6 = $this->sync_flag('Synchronize DHCPv6 server configuration.');
132+
$this->synchronizekea6 = $this->sync_flag('Synchronize Kea DHCPv6 server configuration.');
133+
$this->synchronizedhcrelay = $this->sync_flag('Synchronize DHCP relay configuration.');
134+
$this->synchronizedhcrelay6 = $this->sync_flag('Synchronize DHCPv6 relay configuration.');
135+
$this->synchronizewol = $this->sync_flag('Synchronize Wake-on-LAN configuration.');
136+
$this->synchronizestaticroutes = $this->sync_flag('Synchronize static routes.');
137+
$this->synchronizevirtualip = $this->sync_flag('Synchronize virtual IP addresses.');
138+
$this->synchronizetrafficshaper = $this->sync_flag('Synchronize traffic shaper queues.');
139+
$this->synchronizetrafficshaperlimiter = $this->sync_flag('Synchronize traffic shaper limiters.');
140+
$this->synchronizednsforwarder = $this->sync_flag('Synchronize DNS Forwarder and DNS Resolver configuration.');
141+
$this->synchronizecaptiveportal = $this->sync_flag('Synchronize captive portal configuration.');
142+
143+
parent::__construct($id, $parent_id, $data, ...$options);
144+
}
145+
146+
/**
147+
* pfSense HA Sync checkboxes are stored as the string "on" when enabled.
148+
* When disabled, the XML key should be removed.
149+
*/
150+
private function sync_flag(string $help_text): BooleanField {
151+
return new BooleanField(
152+
default: false,
153+
indicates_true: 'on',
154+
indicates_false: null,
155+
help_text: $help_text,
156+
);
157+
}
158+
159+
/**
160+
* Applies HA Sync configuration changes.
161+
*/
162+
public function apply(): bool|null {
163+
filter_configure_sync();
164+
filter_configure();
165+
166+
return true;
167+
}
168+
}

0 commit comments

Comments
 (0)