e96efc01f22802710f8776089e3cb78763e3b47f
[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::JSONSchema qw(get_standard_option);
6
7 use PVE::Firewall;
8
9 use base qw(PVE::RESTHandler);
10
11 my $api_properties = { 
12     cidr => {
13         description => "Network/IP specification in CIDR format.",
14         type => 'string', format => 'IPv4orCIDR',
15     },
16     name => {
17         description => "IP set name.",
18         type => 'string',
19     },
20     comment => {
21         type => 'string',
22         optional => 1,
23     },
24     nomatch => {
25         type => 'boolean',
26         optional => 1,
27     },
28 };
29
30 sub load_config {
31     my ($class, $param) = @_;
32
33     die "implement this in subclass";
34
35     #return ($fw_conf, $rules);
36 }
37
38 sub save_rules {
39     my ($class, $param, $fw_conf, $rules) = @_;
40
41     die "implement this in subclass";
42 }
43
44 my $additional_param_hash = {};
45
46 sub additional_parameters {
47     my ($class, $new_value) = @_;
48
49     if (defined($new_value)) {
50         $additional_param_hash->{$class} = $new_value;
51     }
52
53     # return a copy
54     my $copy = {};
55     my $org = $additional_param_hash->{$class} || {};
56     foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
57     return $copy;
58 }
59
60 sub register_get_ipset {
61     my ($class) = @_;
62
63     my $properties = $class->additional_parameters();
64
65     $properties->{name} = $api_properties->{name};
66
67     $class->register_method({
68         name => 'get_ipset',
69         path => '',
70         method => 'GET',
71         description => "List IPSet content",
72         parameters => {
73             additionalProperties => 0,
74             properties => $properties,
75         },
76         returns => {
77             type => 'array',
78             items => {
79                 type => "object",
80                 properties => {
81                     cidr => {
82                         type => 'string',
83                     },
84                     comment => {
85                         type => 'string',
86                         optional => 1,
87                     },
88                     nomatch => {
89                         type => 'boolean',
90                         optional => 1,
91                     },                  
92                 },
93             },
94             links => [ { rel => 'child', href => "{cidr}" } ],
95         },
96         code => sub {
97             my ($param) = @_;
98
99             my ($fw_conf, $ipset) = $class->load_config($param);
100
101             return $ipset;
102         }});
103 }
104
105 sub register_add_ip {
106     my ($class) = @_;
107
108     my $properties = $class->additional_parameters();
109
110     $properties->{name} = $api_properties->{name};
111     $properties->{cidr} = $api_properties->{cidr};
112     $properties->{nomatch} = $api_properties->{nomatch};
113     $properties->{comment} = $api_properties->{comment};
114     
115     $class->register_method({
116         name => 'add_ip',
117         path => '',
118         method => 'POST',
119         description => "Add IP or Network to IPSet.",
120         protected => 1,
121         parameters => {
122             additionalProperties => 0,
123             properties => $properties,
124         },
125         returns => { type => "null" },
126         code => sub {
127             my ($param) = @_;
128
129             my ($fw_conf, $ipset) = $class->load_config($param);
130
131             my $data = { cidr => $param->{cidr} };
132             $data->{nomatch} = 1 if $param->{nomatch};
133             $data->{comment} = $param->{comment} if $param->{comment};
134
135             # fixme: verify
136
137             unshift @$ipset, $data;
138
139             $class->save_ipset($param, $fw_conf, $ipset);
140
141             return undef;
142         }});
143 }
144
145 sub register_remove_ip {
146     my ($class) = @_;
147
148     my $properties = $class->additional_parameters();
149
150     $properties->{name} = $api_properties->{name};
151     $properties->{cidr} = $api_properties->{cidr};
152     
153     $class->register_method({
154         name => 'remove_ip',
155         path => '{cidr}',
156         method => 'DELETE',
157         description => "Remove IP or Network from IPSet.",
158         protected => 1,
159         parameters => {
160             additionalProperties => 0,
161             properties => $properties,
162         },
163         returns => { type => "null" },
164         code => sub {
165             my ($param) = @_;
166
167             my ($fw_conf, $ipset) = $class->load_config($param);
168
169             die "implement me $param->{cidr}";
170
171             $class->save_ipset($param, $fw_conf, $ipset);
172
173             return undef;
174         }});
175 }
176
177 sub register_handlers {
178     my ($class) = @_;
179
180     $class->register_get_ipset();
181     $class->register_add_ip();
182     $class->register_remove_ip();
183 }
184
185 package PVE::API2::Firewall::ClusterIPset;
186
187 use strict;
188 use warnings;
189
190 use base qw(PVE::API2::Firewall::IPSetBase);
191
192 sub load_config {
193     my ($class, $param) = @_;
194
195     my $fw_conf = PVE::Firewall::load_clusterfw_conf();
196     my $ipset = $fw_conf->{ipset}->{$param->{name}};
197     die "no such IPSet '$param->{name}'\n" if !defined($ipset);
198
199     return ($fw_conf, $ipset);
200 }
201
202 sub save_ipset {
203     my ($class, $param, $fw_conf, $ipset) = @_;
204
205     $fw_conf->{ipset}->{$param->{name}} = $ipset;
206     PVE::Firewall::save_clusterfw_conf($fw_conf);
207 }
208
209 __PACKAGE__->register_handlers();
210
211 1;