]> git.proxmox.com Git - pve-firewall.git/blob - src/PVE/API2/Firewall/IPSet.pm
3b62346437a4c87daff381326909992df97bc406
[pve-firewall.git] / src / PVE / API2 / Firewall / IPSet.pm
1 package PVE::API2::Firewall::IPSetBase;
2
3 use strict;
4 use warnings;
5 use PVE::Exception qw(raise raise_param_exc);
6 use PVE::JSONSchema qw(get_standard_option);
7
8 use PVE::Firewall;
9
10 use base qw(PVE::RESTHandler);
11
12 my $api_properties = {
13 cidr => {
14 description => "Network/IP specification in CIDR format.",
15 type => 'string', format => 'IPv4orCIDR',
16 },
17 name => {
18 description => "IP set name.",
19 type => 'string',
20 },
21 comment => {
22 type => 'string',
23 optional => 1,
24 },
25 nomatch => {
26 type => 'boolean',
27 optional => 1,
28 },
29 };
30
31 sub load_config {
32 my ($class, $param) = @_;
33
34 die "implement this in subclass";
35
36 #return ($fw_conf, $rules);
37 }
38
39 sub save_rules {
40 my ($class, $param, $fw_conf, $rules) = @_;
41
42 die "implement this in subclass";
43 }
44
45 my $additional_param_hash = {};
46
47 sub additional_parameters {
48 my ($class, $new_value) = @_;
49
50 if (defined($new_value)) {
51 $additional_param_hash->{$class} = $new_value;
52 }
53
54 # return a copy
55 my $copy = {};
56 my $org = $additional_param_hash->{$class} || {};
57 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
58 return $copy;
59 }
60
61 sub register_get_ipset {
62 my ($class) = @_;
63
64 my $properties = $class->additional_parameters();
65
66 $properties->{name} = $api_properties->{name};
67
68 $class->register_method({
69 name => 'get_ipset',
70 path => '',
71 method => 'GET',
72 description => "List IPSet content",
73 parameters => {
74 additionalProperties => 0,
75 properties => $properties,
76 },
77 returns => {
78 type => 'array',
79 items => {
80 type => "object",
81 properties => {
82 cidr => {
83 type => 'string',
84 },
85 comment => {
86 type => 'string',
87 optional => 1,
88 },
89 nomatch => {
90 type => 'boolean',
91 optional => 1,
92 },
93 },
94 },
95 links => [ { rel => 'child', href => "{cidr}" } ],
96 },
97 code => sub {
98 my ($param) = @_;
99
100 my ($fw_conf, $ipset) = $class->load_config($param);
101
102 return $ipset;
103 }});
104 }
105
106 sub register_create_ip {
107 my ($class) = @_;
108
109 my $properties = $class->additional_parameters();
110
111 $properties->{name} = $api_properties->{name};
112 $properties->{cidr} = $api_properties->{cidr};
113 $properties->{nomatch} = $api_properties->{nomatch};
114 $properties->{comment} = $api_properties->{comment};
115
116 $class->register_method({
117 name => 'create_ip',
118 path => '',
119 method => 'POST',
120 description => "Add IP or Network to IPSet.",
121 protected => 1,
122 parameters => {
123 additionalProperties => 0,
124 properties => $properties,
125 },
126 returns => { type => "null" },
127 code => sub {
128 my ($param) = @_;
129
130 my ($fw_conf, $ipset) = $class->load_config($param);
131
132 my $cidr = $param->{cidr};
133
134 foreach my $entry (@$ipset) {
135 raise_param_exc({ cidr => "address '$cidr' already exists" })
136 if $entry->{cidr} eq $cidr;
137 }
138
139 my $data = { cidr => $cidr };
140 $data->{nomatch} = 1 if $param->{nomatch};
141 $data->{comment} = $param->{comment} if $param->{comment};
142
143 unshift @$ipset, $data;
144
145 $class->save_ipset($param, $fw_conf, $ipset);
146
147 return undef;
148 }});
149 }
150
151 sub register_read_ip {
152 my ($class) = @_;
153
154 my $properties = $class->additional_parameters();
155
156 $properties->{name} = $api_properties->{name};
157 $properties->{cidr} = $api_properties->{cidr};
158
159 $class->register_method({
160 name => 'read_ip',
161 path => '{cidr}',
162 method => 'GET',
163 description => "Read IP or Network settings from IPSet.",
164 protected => 1,
165 parameters => {
166 additionalProperties => 0,
167 properties => $properties,
168 },
169 returns => { type => "object" },
170 code => sub {
171 my ($param) = @_;
172
173 my ($fw_conf, $ipset) = $class->load_config($param);
174
175 foreach my $entry (@$ipset) {
176 return $entry if $entry->{cidr} eq $param->{cidr};
177 }
178
179 raise_param_exc({ cidr => "no such IP/Network" });
180 }});
181 }
182
183 sub register_update_ip {
184 my ($class) = @_;
185
186 my $properties = $class->additional_parameters();
187
188 $properties->{name} = $api_properties->{name};
189 $properties->{cidr} = $api_properties->{cidr};
190 $properties->{nomatch} = $api_properties->{nomatch};
191 $properties->{comment} = $api_properties->{comment};
192
193 $class->register_method({
194 name => 'update_ip',
195 path => '{cidr}',
196 method => 'PUT',
197 description => "Update IP or Network settings",
198 protected => 1,
199 parameters => {
200 additionalProperties => 0,
201 properties => $properties,
202 },
203 returns => { type => "null" },
204 code => sub {
205 my ($param) = @_;
206
207 my ($fw_conf, $ipset) = $class->load_config($param);
208
209 foreach my $entry (@$ipset) {
210 if($entry->{cidr} eq $param->{cidr}) {
211 $entry->{nomatch} = $param->{nomatch};
212 $entry->{comment} = $param->{comment};
213 $class->save_ipset($param, $fw_conf, $ipset);
214 return;
215 }
216 }
217
218 raise_param_exc({ cidr => "no such IP/Network" });
219 }});
220 }
221
222 sub register_delete_ip {
223 my ($class) = @_;
224
225 my $properties = $class->additional_parameters();
226
227 $properties->{name} = $api_properties->{name};
228 $properties->{cidr} = $api_properties->{cidr};
229
230 $class->register_method({
231 name => 'remove_ip',
232 path => '{cidr}',
233 method => 'DELETE',
234 description => "Remove IP or Network from IPSet.",
235 protected => 1,
236 parameters => {
237 additionalProperties => 0,
238 properties => $properties,
239 },
240 returns => { type => "null" },
241 code => sub {
242 my ($param) = @_;
243
244 my ($fw_conf, $ipset) = $class->load_config($param);
245
246 my $new = [];
247
248 foreach my $entry (@$ipset) {
249 push @$new, $entry if $entry->{cidr} ne $param->{cidr};
250 }
251
252 $class->save_ipset($param, $fw_conf, $new);
253
254 return undef;
255 }});
256 }
257
258 sub register_handlers {
259 my ($class) = @_;
260
261 $class->register_get_ipset();
262 $class->register_create_ip();
263 $class->register_read_ip();
264 $class->register_update_ip();
265 $class->register_delete_ip();
266 }
267
268 package PVE::API2::Firewall::ClusterIPset;
269
270 use strict;
271 use warnings;
272
273 use base qw(PVE::API2::Firewall::IPSetBase);
274
275 sub load_config {
276 my ($class, $param) = @_;
277
278 my $fw_conf = PVE::Firewall::load_clusterfw_conf();
279 my $ipset = $fw_conf->{ipset}->{$param->{name}};
280 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
281
282 return ($fw_conf, $ipset);
283 }
284
285 sub save_ipset {
286 my ($class, $param, $fw_conf, $ipset) = @_;
287
288 $fw_conf->{ipset}->{$param->{name}} = $ipset;
289 PVE::Firewall::save_clusterfw_conf($fw_conf);
290 }
291
292 __PACKAGE__->register_handlers();
293
294 1;