]> git.proxmox.com Git - pve-firewall.git/blame - src/pvefw
allow options and rules section in cluster.fw
[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 {
3f95d14a
DM
63 my ($ruleset, $hostfw_conf, $ipset_ruleset) = PVE::Firewall::compile();
64
65 if ($param->{verbose}) {
66 my (undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset, 1);
67 my (undef, $ruleset_changes) = PVE::Firewall::get_rulset_cmdlist($ruleset, 1);
68 if ($ipset_changes || $ruleset_changes) {
69 print "detected changes\n";
70 } else {
71 print "no changes\n";
72 }
73 }
06320eb0
DM
74 };
75
76 PVE::Firewall::run_locked($code);
f789653a 77
5e1267a5
DM
78 return undef;
79 }});
80bfe1ff 80
6b9f68a2
DM
81__PACKAGE__->register_method ({
82 name => 'status',
83 path => 'status',
84 method => 'GET',
85 description => "Get firewall status.",
86 parameters => {
87 additionalProperties => 0,
88 properties => {},
89 },
90 returns => {
91 type => 'object',
92 additionalProperties => 0,
93 properties => {
94 status => {
95 type => 'string',
96 enum => ['unknown', 'stopped', 'active'],
97 },
98 changes => {
99 description => "Set when there are pending changes.",
100 type => 'boolean',
101 optional => 1,
102 }
103 },
104 },
105 code => sub {
106 my ($param) = @_;
107
108 my $rpcenv = PVE::RPCEnvironment::get();
109
110 $param->{verbose} = 1
111 if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli');
112
113 my $code = sub {
114 my $status = PVE::Firewall::read_pvefw_status();
115
116 my $res = { status => $status };
117 if ($status eq 'active') {
3f95d14a 118 my ($ruleset, $hostfw_conf, $ipset_ruleset) = PVE::Firewall::compile();
6b9f68a2 119
3f95d14a
DM
120 my (undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset);
121 my (undef, $ruleset_changes) = PVE::Firewall::get_rulset_cmdlist($ruleset);
122 # fixme: ipset changes
123 $res->{changes} = ($ipset_changes || $ruleset_changes) ? 1 : 0;
6b9f68a2
DM
124 }
125
126 return $res;
127 };
128
129 return PVE::Firewall::run_locked($code);
130 }});
131
5e1267a5
DM
132__PACKAGE__->register_method ({
133 name => 'start',
134 path => 'start',
135 method => 'POST',
6b9f68a2 136 description => "Start (or simply update if already active) firewall.",
5e1267a5
DM
137 parameters => {
138 additionalProperties => 0,
3fa83edf
DM
139 properties => {
140 verbose => {
141 description => "Verbose output.",
142 type => "boolean",
143 optional => 1,
144 default => 0,
145 },
146 },
5e1267a5
DM
147 },
148 returns => { type => 'null' },
80bfe1ff 149
5e1267a5
DM
150 code => sub {
151 my ($param) = @_;
80bfe1ff 152
6b9f68a2 153 PVE::Firewall::update(1, $param->{verbose});
06320eb0 154
6b9f68a2
DM
155 return undef;
156 }});
157
158__PACKAGE__->register_method ({
159 name => 'update',
160 path => 'update',
161 method => 'POST',
162 description => "Check firewall rules. Then update the rules if the firewall is active.",
163 parameters => {
164 additionalProperties => 0,
165 properties => {
166 verbose => {
167 description => "Verbose output.",
168 type => "boolean",
169 optional => 1,
170 default => 0,
171 },
172 },
173 },
174 returns => { type => 'null' },
175
176 code => sub {
177 my ($param) = @_;
178
179 PVE::Firewall::update(0, $param->{verbose});
80bfe1ff
DM
180
181 return undef;
80bfe1ff
DM
182 }});
183
80bfe1ff
DM
184__PACKAGE__->register_method ({
185 name => 'stop',
186 path => 'stop',
187 method => 'POST',
a332200b 188 description => "Stop firewall. This will remove all rules installed by this script. The host is then unprotected.",
80bfe1ff
DM
189 parameters => {
190 additionalProperties => 0,
191 properties => {},
192 },
193 returns => { type => 'null' },
194
195 code => sub {
196 my ($param) = @_;
197
06320eb0 198 my $code = sub {
6b9f68a2 199
b16e818e
DM
200 my $chash = PVE::Firewall::iptables_get_chains();
201 my $cmdlist = "*filter\n";
dec84fcd 202 my $rule = "INPUT -j PVEFW-INPUT";
3fa83edf
DM
203 if (PVE::Firewall::iptables_rule_exist($rule)) {
204 $cmdlist .= "-D $rule\n";
205 }
dec84fcd 206 $rule = "OUTPUT -j PVEFW-OUTPUT";
3fa83edf
DM
207 if (PVE::Firewall::iptables_rule_exist($rule)) {
208 $cmdlist .= "-D $rule\n";
209 }
210
dec84fcd 211 $rule = "FORWARD -j PVEFW-FORWARD";
3fa83edf
DM
212 if (PVE::Firewall::iptables_rule_exist($rule)) {
213 $cmdlist .= "-D $rule\n";
214 }
215
b16e818e
DM
216 foreach my $chain (keys %$chash) {
217 $cmdlist .= "-F $chain\n";
218 }
219 foreach my $chain (keys %$chash) {
220 $cmdlist .= "-X $chain\n";
221 }
222 $cmdlist .= "COMMIT\n";
223
224 PVE::Firewall::iptables_restore_cmdlist($cmdlist);
6b9f68a2
DM
225
226 PVE::Firewall::save_pvefw_status('stopped');
06320eb0
DM
227 };
228
229 PVE::Firewall::run_locked($code);
80bfe1ff
DM
230
231 return undef;
232 }});
233
234my $nodename = PVE::INotify::nodename();
235
236my $cmddef = {
237 compile => [ __PACKAGE__, 'compile', []],
238 start => [ __PACKAGE__, 'start', []],
6b9f68a2
DM
239 update => [ __PACKAGE__, 'update', []],
240 status => [ __PACKAGE__, 'status', [], undef, sub {
241 my $res = shift;
242 if ($res->{changes}) {
243 print "Status: $res->{status} (pending changes)\n";
244 } else {
245 print "Status: $res->{status}\n";
246 }
247 }],
80bfe1ff 248 stop => [ __PACKAGE__, 'stop', []],
8f119284
DM
249
250 # This is for debugging
251 listgroups => [ 'PVE::API2::Firewall::Groups', 'list', [],
252 { node => $nodename }, sub {
253 my $res = shift;
254 print Dumper($res);
255 }],
d1c53b3e
DM
256 grouprules => [ 'PVE::API2::Firewall::Groups', 'get_rules', ['group'],
257 { node => $nodename }, sub {
258 my $res = shift;
259 print Dumper($res);
260 }],
80bfe1ff
DM
261};
262
263my $cmd = shift;
264
265PVE::CLIHandler::handle_cmd($cmddef, "pvefw", $cmd, \@ARGV, undef, $0);
b6360c3f
DM
266
267exit(0);
80bfe1ff 268