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