]> git.proxmox.com Git - pve-firewall.git/blob - src/pvefw
improve parameter verification
[pve-firewall.git] / src / pvefw
1 #!/usr/bin/perl -T
2
3 use strict;
4 use warnings;
5
6 use lib qw(.);
7 use PVE::Firewall;
8
9 use PVE::SafeSyslog;
10 use PVE::Cluster;
11 use PVE::INotify;
12 use PVE::RPCEnvironment;
13
14 use PVE::JSONSchema qw(get_standard_option);
15
16 use PVE::CLIHandler;
17 use PVE::API2::Firewall::Groups;
18
19 use base qw(PVE::CLIHandler);
20
21 use Data::Dumper;
22
23 $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
24
25 initlog ('pvefw');
26
27 die "please run as root\n" if $> != 0;
28
29 PVE::INotify::inotify_init();
30
31 my $rpcenv = PVE::RPCEnvironment->init('cli');
32
33 $rpcenv->init_request();
34 $rpcenv->set_language($ENV{LANG});
35 $rpcenv->set_user('root@pam');
36
37 __PACKAGE__->register_method ({
38 name => 'compile',
39 path => 'compile',
40 method => 'POST',
41 description => "Compile amd print firewall rules. This is only for testing.",
42 parameters => {
43 additionalProperties => 0,
44 properties => {
45 verbose => {
46 description => "Verbose output.",
47 type => "boolean",
48 optional => 1,
49 },
50 },
51 },
52 returns => { type => 'null' },
53
54 code => sub {
55 my ($param) = @_;
56
57 my $rpcenv = PVE::RPCEnvironment::get();
58
59 $param->{verbose} = 1
60 if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli');
61
62 my $code = sub {
63 my $ruleset = PVE::Firewall::compile();
64 PVE::Firewall::get_ruleset_status($ruleset, 1) if $param->{verbose};
65 };
66
67 PVE::Firewall::run_locked($code);
68
69 return undef;
70 }});
71
72 __PACKAGE__->register_method ({
73 name => 'status',
74 path => 'status',
75 method => 'GET',
76 description => "Get firewall status.",
77 parameters => {
78 additionalProperties => 0,
79 properties => {},
80 },
81 returns => {
82 type => 'object',
83 additionalProperties => 0,
84 properties => {
85 status => {
86 type => 'string',
87 enum => ['unknown', 'stopped', 'active'],
88 },
89 changes => {
90 description => "Set when there are pending changes.",
91 type => 'boolean',
92 optional => 1,
93 }
94 },
95 },
96 code => sub {
97 my ($param) = @_;
98
99 my $rpcenv = PVE::RPCEnvironment::get();
100
101 $param->{verbose} = 1
102 if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli');
103
104 my $code = sub {
105 my $status = PVE::Firewall::read_pvefw_status();
106
107 my $res = { status => $status };
108 if ($status eq 'active') {
109 my $ruleset = PVE::Firewall::compile();
110 my $cmdlist = PVE::Firewall::get_rulset_cmdlist($ruleset);
111
112 if ($cmdlist ne "*filter\nCOMMIT\n") {
113 $res->{changes} = 1;
114 }
115 }
116
117 return $res;
118 };
119
120 return PVE::Firewall::run_locked($code);
121 }});
122
123 __PACKAGE__->register_method ({
124 name => 'start',
125 path => 'start',
126 method => 'POST',
127 description => "Start (or simply update if already active) firewall.",
128 parameters => {
129 additionalProperties => 0,
130 properties => {
131 verbose => {
132 description => "Verbose output.",
133 type => "boolean",
134 optional => 1,
135 default => 0,
136 },
137 },
138 },
139 returns => { type => 'null' },
140
141 code => sub {
142 my ($param) = @_;
143
144 PVE::Firewall::update(1, $param->{verbose});
145
146 return undef;
147 }});
148
149 __PACKAGE__->register_method ({
150 name => 'update',
151 path => 'update',
152 method => 'POST',
153 description => "Check firewall rules. Then update the rules if the firewall is active.",
154 parameters => {
155 additionalProperties => 0,
156 properties => {
157 verbose => {
158 description => "Verbose output.",
159 type => "boolean",
160 optional => 1,
161 default => 0,
162 },
163 },
164 },
165 returns => { type => 'null' },
166
167 code => sub {
168 my ($param) = @_;
169
170 PVE::Firewall::update(0, $param->{verbose});
171
172 return undef;
173 }});
174
175 __PACKAGE__->register_method ({
176 name => 'stop',
177 path => 'stop',
178 method => 'POST',
179 description => "Stop firewall. This will remove all rules installed by this script. The host is then unprotected.",
180 parameters => {
181 additionalProperties => 0,
182 properties => {},
183 },
184 returns => { type => 'null' },
185
186 code => sub {
187 my ($param) = @_;
188
189 my $code = sub {
190
191 my $chash = PVE::Firewall::iptables_get_chains();
192 my $cmdlist = "*filter\n";
193 my $rule = "INPUT -j PVEFW-INPUT";
194 if (PVE::Firewall::iptables_rule_exist($rule)) {
195 $cmdlist .= "-D $rule\n";
196 }
197 $rule = "OUTPUT -j PVEFW-OUTPUT";
198 if (PVE::Firewall::iptables_rule_exist($rule)) {
199 $cmdlist .= "-D $rule\n";
200 }
201
202 $rule = "FORWARD -j PVEFW-FORWARD";
203 if (PVE::Firewall::iptables_rule_exist($rule)) {
204 $cmdlist .= "-D $rule\n";
205 }
206
207 foreach my $chain (keys %$chash) {
208 $cmdlist .= "-F $chain\n";
209 }
210 foreach my $chain (keys %$chash) {
211 $cmdlist .= "-X $chain\n";
212 }
213 $cmdlist .= "COMMIT\n";
214
215 PVE::Firewall::iptables_restore_cmdlist($cmdlist);
216
217 PVE::Firewall::save_pvefw_status('stopped');
218 };
219
220 PVE::Firewall::run_locked($code);
221
222 return undef;
223 }});
224
225 my $nodename = PVE::INotify::nodename();
226
227 my $cmddef = {
228 compile => [ __PACKAGE__, 'compile', []],
229 start => [ __PACKAGE__, 'start', []],
230 update => [ __PACKAGE__, 'update', []],
231 status => [ __PACKAGE__, 'status', [], undef, sub {
232 my $res = shift;
233 if ($res->{changes}) {
234 print "Status: $res->{status} (pending changes)\n";
235 } else {
236 print "Status: $res->{status}\n";
237 }
238 }],
239 stop => [ __PACKAGE__, 'stop', []],
240
241 # This is for debugging
242 listgroups => [ 'PVE::API2::Firewall::Groups', 'list', [],
243 { node => $nodename }, sub {
244 my $res = shift;
245 print Dumper($res);
246 }],
247 grouprules => [ 'PVE::API2::Firewall::Groups', 'get_rules', ['group'],
248 { node => $nodename }, sub {
249 my $res = shift;
250 print Dumper($res);
251 }],
252 };
253
254 my $cmd = shift;
255
256 PVE::CLIHandler::handle_cmd($cmddef, "pvefw", $cmd, \@ARGV, undef, $0);
257
258 exit(0);
259