start host API
[pve-firewall.git] / src / pvefw
CommitLineData
11388be7 1#!/usr/bin/perl -T
b6360c3f
DM
2
3use strict;
c2dca086
DM
4use warnings;
5
b6360c3f
DM
6use lib qw(.);
7use PVE::Firewall;
dddd9413 8
80bfe1ff
DM
9use PVE::SafeSyslog;
10use PVE::Cluster;
11use PVE::INotify;
12use PVE::RPCEnvironment;
b6360c3f 13
80bfe1ff
DM
14use PVE::JSONSchema qw(get_standard_option);
15
16use PVE::CLIHandler;
8f119284 17use PVE::API2::Firewall::Groups;
80bfe1ff
DM
18
19use base qw(PVE::CLIHandler);
20
8f119284
DM
21use Data::Dumper;
22
80bfe1ff
DM
23$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
24
25initlog ('pvefw');
26
27die "please run as root\n" if $> != 0;
28
29PVE::INotify::inotify_init();
30
31my $rpcenv = PVE::RPCEnvironment->init('cli');
32
33$rpcenv->init_request();
34$rpcenv->set_language($ENV{LANG});
35$rpcenv->set_user('root@pam');
b6360c3f 36
80bfe1ff
DM
37__PACKAGE__->register_method ({
38 name => 'compile',
39 path => 'compile',
40 method => 'POST',
3fa83edf 41 description => "Compile amd print firewall rules. This is only for testing.",
80bfe1ff
DM
42 parameters => {
43 additionalProperties => 0,
3fa83edf
DM
44 properties => {
45 verbose => {
46 description => "Verbose output.",
47 type => "boolean",
48 optional => 1,
3fa83edf
DM
49 },
50 },
80bfe1ff
DM
51 },
52 returns => { type => 'null' },
53
54 code => sub {
55 my ($param) = @_;
56
e0809a95
DM
57 my $rpcenv = PVE::RPCEnvironment::get();
58
59 $param->{verbose} = 1
60 if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli');
61
06320eb0 62 my $code = sub {
3fa83edf
DM
63 my $ruleset = PVE::Firewall::compile();
64 PVE::Firewall::get_ruleset_status($ruleset, 1) if $param->{verbose};
06320eb0
DM
65 };
66
67 PVE::Firewall::run_locked($code);
f789653a 68
5e1267a5
DM
69 return undef;
70 }});
80bfe1ff 71
6b9f68a2
DM
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
5e1267a5
DM
123__PACKAGE__->register_method ({
124 name => 'start',
125 path => 'start',
126 method => 'POST',
6b9f68a2 127 description => "Start (or simply update if already active) firewall.",
5e1267a5
DM
128 parameters => {
129 additionalProperties => 0,
3fa83edf
DM
130 properties => {
131 verbose => {
132 description => "Verbose output.",
133 type => "boolean",
134 optional => 1,
135 default => 0,
136 },
137 },
5e1267a5
DM
138 },
139 returns => { type => 'null' },
80bfe1ff 140
5e1267a5
DM
141 code => sub {
142 my ($param) = @_;
80bfe1ff 143
6b9f68a2 144 PVE::Firewall::update(1, $param->{verbose});
06320eb0 145
6b9f68a2
DM
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});
80bfe1ff
DM
171
172 return undef;
80bfe1ff
DM
173 }});
174
80bfe1ff
DM
175__PACKAGE__->register_method ({
176 name => 'stop',
177 path => 'stop',
178 method => 'POST',
a332200b 179 description => "Stop firewall. This will remove all rules installed by this script. The host is then unprotected.",
80bfe1ff
DM
180 parameters => {
181 additionalProperties => 0,
182 properties => {},
183 },
184 returns => { type => 'null' },
185
186 code => sub {
187 my ($param) = @_;
188
06320eb0 189 my $code = sub {
6b9f68a2 190
b16e818e
DM
191 my $chash = PVE::Firewall::iptables_get_chains();
192 my $cmdlist = "*filter\n";
dec84fcd 193 my $rule = "INPUT -j PVEFW-INPUT";
3fa83edf
DM
194 if (PVE::Firewall::iptables_rule_exist($rule)) {
195 $cmdlist .= "-D $rule\n";
196 }
dec84fcd 197 $rule = "OUTPUT -j PVEFW-OUTPUT";
3fa83edf
DM
198 if (PVE::Firewall::iptables_rule_exist($rule)) {
199 $cmdlist .= "-D $rule\n";
200 }
201
dec84fcd 202 $rule = "FORWARD -j PVEFW-FORWARD";
3fa83edf
DM
203 if (PVE::Firewall::iptables_rule_exist($rule)) {
204 $cmdlist .= "-D $rule\n";
205 }
206
b16e818e
DM
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);
6b9f68a2
DM
216
217 PVE::Firewall::save_pvefw_status('stopped');
06320eb0
DM
218 };
219
220 PVE::Firewall::run_locked($code);
80bfe1ff
DM
221
222 return undef;
223 }});
224
225my $nodename = PVE::INotify::nodename();
226
227my $cmddef = {
228 compile => [ __PACKAGE__, 'compile', []],
229 start => [ __PACKAGE__, 'start', []],
6b9f68a2
DM
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 }],
80bfe1ff 239 stop => [ __PACKAGE__, 'stop', []],
8f119284
DM
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 }],
d1c53b3e
DM
247 grouprules => [ 'PVE::API2::Firewall::Groups', 'get_rules', ['group'],
248 { node => $nodename }, sub {
249 my $res = shift;
250 print Dumper($res);
251 }],
80bfe1ff
DM
252};
253
254my $cmd = shift;
255
256PVE::CLIHandler::handle_cmd($cmddef, "pvefw", $cmd, \@ARGV, undef, $0);
b6360c3f
DM
257
258exit(0);
80bfe1ff 259