4ea2f77eff66f85dca1ebb04c194e7d04825eb90
[pve-firewall.git] / src / PVE / API2 / Firewall / Groups.pm
1 package PVE::API2::Firewall::Groups;
2
3 use strict;
4 use warnings;
5 use PVE::JSONSchema qw(get_standard_option);
6
7 use PVE::Firewall;
8
9
10 use Data::Dumper; # fixme: remove
11
12 use base qw(PVE::RESTHandler);
13
14 __PACKAGE__->register_method({
15     name => 'list',
16     path => '',
17     method => 'GET',
18     description => "List security groups.",
19     proxyto => 'node',
20     parameters => {
21         additionalProperties => 0,
22         properties => {
23             node => get_standard_option('pve-node'),
24         },
25     },
26     returns => {
27         type => 'array',
28         items => {
29             type => "object",
30             properties => { 
31                 name => {
32                     description => "Security group name.",
33                     type => 'string',
34                 },
35             },
36         },
37         links => [ { rel => 'child', href => "{name}" } ],
38     },
39     code => sub {
40         my ($param) = @_;
41
42         my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
43
44         my $res = [];
45         foreach my $group (keys %{$cluster_conf->{rules}}) {
46             push @$res, { name => $group, count => scalar(@{$cluster_conf->{rules}->{$group}}) };
47         }
48
49         return $res;
50     }});
51
52 __PACKAGE__->register_method({
53     name => 'get_rules',
54     path => '{group}',
55     method => 'GET',
56     description => "List security groups rules.",
57     proxyto => 'node',
58     parameters => {
59         additionalProperties => 0,
60         properties => {
61             node => get_standard_option('pve-node'),
62             group => {
63                 description => "Security group name.",
64                 type => 'string',
65             },
66         },
67     },
68     returns => {
69         type => 'array',
70         items => {
71             type => "object",
72             properties => {
73                 pos => {
74                     type => 'integer',
75                 }
76             },
77         },
78         links => [ { rel => 'child', href => "{pos}" } ],
79     },
80     code => sub {
81         my ($param) = @_;
82
83         my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
84
85         my $rules = $cluster_conf->{rules}->{$param->{group}};
86         die "no such security group\n" if !defined($rules);
87
88         my $digest = $cluster_conf->{digest};
89
90         my $res = [];
91
92         my $ind = 0;
93         foreach my $rule (@$rules) {
94             push @$res, PVE::Firewall::cleanup_fw_rule($rule, $digest, $ind++);
95         }
96
97         return $res;
98     }});
99
100 __PACKAGE__->register_method({
101     name => 'get_rule',
102     path => '{group}/{pos}',
103     method => 'GET',
104     description => "Get single rule data.",
105     proxyto => 'node',
106     parameters => {
107         additionalProperties => 0,
108         properties => {
109             node => get_standard_option('pve-node'),
110             group => {
111                 description => "Security group name.",
112                 type => 'string',
113             },
114             pos => {
115                 description => "Return rule from position <pos>.",
116                 type => 'integer',
117                 minimum => 0,
118             },
119         },
120     },
121     returns => {
122         type => "object",
123         properties => {
124             pos => {
125                 type => 'integer',
126             }
127         },
128     },
129     code => sub {
130         my ($param) = @_;
131
132         my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
133
134         my $rules = $cluster_conf->{rules}->{$param->{group}};
135         die "no such security group\n" if !defined($rules);
136
137         my $digest = $cluster_conf->{digest};
138         # fixme: check digest
139         
140         die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
141         
142         my $rule = $rules->[$param->{pos}];
143
144         return PVE::Firewall::cleanup_fw_rule($rule, $digest, $param->{pos});
145    }});
146
147
148 __PACKAGE__->register_method({
149     name => 'create_rule',
150     path => '{group}',
151     method => 'POST',
152     description => "Create new rule.",
153     proxyto => 'node',
154     protected => 1,
155     parameters => {
156         additionalProperties => 0,
157         properties => PVE::Firewall::add_rule_properties({
158             node => get_standard_option('pve-node'),
159             group => {
160                 description => "Security group name.",
161                 type => 'string',
162             },
163         }),
164     },
165     returns => { type => "null" },
166     code => sub {
167         my ($param) = @_;
168
169         my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
170
171         my $rules = $cluster_conf->{rules}->{$param->{group}};
172         die "no such security group\n" if !defined($rules);
173
174         my $digest = $cluster_conf->{digest};
175                 
176         my $rule = { type => 'out', action => 'ACCEPT', enable => 0};
177
178         PVE::Firewall::copy_rule_data($rule, $param);
179
180         unshift @$rules, $rule;
181
182         PVE::Firewall::save_clusterfw_conf($cluster_conf);
183
184         return undef;
185    }});
186
187 __PACKAGE__->register_method({
188     name => 'update_rule',
189     path => '{group}/{pos}',
190     method => 'PUT',
191     description => "Modify rule data.",
192     proxyto => 'node',
193     protected => 1,
194     parameters => {
195         additionalProperties => 0,
196         properties => PVE::Firewall::add_rule_properties({
197             node => get_standard_option('pve-node'),
198             group => {
199                 description => "Security group name.",
200                 type => 'string',
201             },
202             moveto => {
203                 description => "Move rule to new position <moveto>. Other arguments are ignored.",
204                 type => 'integer',
205                 minimum => 0,
206                 optional => 1,
207             },
208         }),
209     },
210     returns => { type => "null" },
211     code => sub {
212         my ($param) = @_;
213
214         my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
215
216         my $rules = $cluster_conf->{rules}->{$param->{group}};
217         die "no such security group\n" if !defined($rules);
218
219         my $digest = $cluster_conf->{digest};
220         # fixme: check digest
221         
222         die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
223         
224         my $rule = $rules->[$param->{pos}];
225
226         my $moveto = $param->{moveto};
227         if (defined($moveto) && $moveto != $param->{pos}) {
228             my $newrules = [];
229             for (my $i = 0; $i < scalar(@$rules); $i++) {
230                 next if $i == $param->{pos};
231                 if ($i == $moveto) {
232                     push @$newrules, $rule;
233                 }
234                 push @$newrules, $rules->[$i];
235             }
236             push @$newrules, $rule if $moveto >= scalar(@$rules);
237
238             $cluster_conf->{rules}->{$param->{group}} = $newrules;
239         } else {
240             PVE::Firewall::copy_rule_data($rule, $param);
241         }
242
243         PVE::Firewall::save_clusterfw_conf($cluster_conf);
244
245         return undef;
246    }});
247
248 __PACKAGE__->register_method({
249     name => 'delete_rule',
250     path => '{group}/{pos}',
251     method => 'DELETE',
252     description => "Delete rule.",
253     proxyto => 'node',
254     protected => 1,
255     parameters => {
256         additionalProperties => 0,
257         properties => {
258             node => get_standard_option('pve-node'),
259             group => {
260                 description => "Security group name.",
261                 type => 'string',
262             },
263             pos => {
264                 description => "Delete rule at position <pos>.",
265                 type => 'integer',
266                 minimum => 0,
267             },
268         },
269     },
270     returns => { type => "null" },
271     code => sub {
272         my ($param) = @_;
273
274         my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
275
276         my $rules = $cluster_conf->{rules}->{$param->{group}};
277         die "no such security group\n" if !defined($rules);
278
279         my $digest = $cluster_conf->{digest};
280         # fixme: check digest
281         
282         die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
283         
284         splice(@$rules, $param->{pos}, 1);
285
286         PVE::Firewall::save_clusterfw_conf($cluster_conf);
287
288         return undef;
289    }});
290
291 1;