]> git.proxmox.com Git - pve-firewall.git/blob - src/PVE/API2/Firewall/IPSet.pm
ipset: implement delete API, improve parameter verification
[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_add_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 => 'add_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_remove_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 => 'remove_ip',
161 path => '{cidr}',
162 method => 'DELETE',
163 description => "Remove IP or Network from IPSet.",
164 protected => 1,
165 parameters => {
166 additionalProperties => 0,
167 properties => $properties,
168 },
169 returns => { type => "null" },
170 code => sub {
171 my ($param) = @_;
172
173 my ($fw_conf, $ipset) = $class->load_config($param);
174
175 my $new = [];
176
177 foreach my $entry (@$ipset) {
178 push @$new, $entry if $entry->{cidr} ne $param->{cidr};
179 }
180
181 $class->save_ipset($param, $fw_conf, $new);
182
183 return undef;
184 }});
185 }
186
187 sub register_handlers {
188 my ($class) = @_;
189
190 $class->register_get_ipset();
191 $class->register_add_ip();
192 $class->register_remove_ip();
193 }
194
195 package PVE::API2::Firewall::ClusterIPset;
196
197 use strict;
198 use warnings;
199
200 use base qw(PVE::API2::Firewall::IPSetBase);
201
202 sub load_config {
203 my ($class, $param) = @_;
204
205 my $fw_conf = PVE::Firewall::load_clusterfw_conf();
206 my $ipset = $fw_conf->{ipset}->{$param->{name}};
207 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
208
209 return ($fw_conf, $ipset);
210 }
211
212 sub save_ipset {
213 my ($class, $param, $fw_conf, $ipset) = @_;
214
215 $fw_conf->{ipset}->{$param->{name}} = $ipset;
216 PVE::Firewall::save_clusterfw_conf($fw_conf);
217 }
218
219 __PACKAGE__->register_handlers();
220
221 1;