]>
Commit | Line | Data |
---|---|---|
36069192 DM |
1 | package PMG::API2::Config; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
be6e2db9 | 5 | use Data::Dumper; |
36069192 DM |
6 | |
7 | use PVE::SafeSyslog; | |
8 | use PVE::Tools qw(extract_param); | |
9 | use HTTP::Status qw(:constants); | |
10 | use Storable qw(dclone); | |
11 | use PVE::JSONSchema qw(get_standard_option); | |
12 | use PVE::RESTHandler; | |
b7f1924f | 13 | use Time::HiRes qw(); |
36069192 DM |
14 | |
15 | use PMG::Config; | |
bdcc6f0f | 16 | use PMG::API2::RuleDB; |
be6d6ffc | 17 | use PMG::API2::LDAP; |
5b2bb556 | 18 | use PMG::API2::Domains; |
3118b703 | 19 | use PMG::API2::Transport; |
fb5f2d1e | 20 | use PMG::API2::Cluster; |
bef31f06 | 21 | use PMG::API2::MyNetworks; |
16fdeb84 | 22 | use PMG::API2::SMTPWhitelist; |
e29ebc7c | 23 | use PMG::API2::MimeTypes; |
c3346bf1 | 24 | use PMG::API2::Fetchmail; |
29fa7feb | 25 | use PMG::API2::DestinationTLSPolicy; |
36069192 DM |
26 | |
27 | use base qw(PVE::RESTHandler); | |
28 | ||
29 | my $section_type_enum = PMG::Config::Base->lookup_types(); | |
30 | ||
bdcc6f0f DM |
31 | __PACKAGE__->register_method ({ |
32 | subclass => "PMG::API2::RuleDB", | |
33 | path => 'ruledb', | |
34 | }); | |
35 | ||
16fdeb84 DM |
36 | __PACKAGE__->register_method ({ |
37 | subclass => "PMG::API2::SMTPWhitelist", | |
38 | path => 'whitelist', | |
39 | }); | |
40 | ||
be6d6ffc DM |
41 | __PACKAGE__->register_method ({ |
42 | subclass => "PMG::API2::LDAP", | |
43 | path => 'ldap', | |
44 | }); | |
bdcc6f0f | 45 | |
5b2bb556 DM |
46 | __PACKAGE__->register_method ({ |
47 | subclass => "PMG::API2::Domains", | |
48 | path => 'domains', | |
c3346bf1 DM |
49 | }); |
50 | ||
51 | __PACKAGE__->register_method ({ | |
52 | subclass => "PMG::API2::Fetchmail", | |
53 | path => 'fetchmail', | |
5b2bb556 DM |
54 | }); |
55 | ||
3118b703 DM |
56 | __PACKAGE__->register_method ({ |
57 | subclass => "PMG::API2::Transport", | |
58 | path => 'transport', | |
59 | }); | |
60 | ||
bef31f06 DM |
61 | __PACKAGE__->register_method ({ |
62 | subclass => "PMG::API2::MyNetworks", | |
63 | # set fragment delimiter (no subdirs) - we need that, because CIDRs | |
64 | # contain a slash '/' | |
65 | fragmentDelimiter => '', | |
66 | path => 'mynetworks', | |
67 | }); | |
68 | ||
5ac6bd0e | 69 | __PACKAGE__->register_method ({ |
fb5f2d1e | 70 | subclass => "PMG::API2::Cluster", |
5ac6bd0e DM |
71 | path => 'cluster', |
72 | }); | |
5b2bb556 | 73 | |
e29ebc7c DC |
74 | __PACKAGE__->register_method ({ |
75 | subclass => "PMG::API2::MimeTypes", | |
76 | path => 'mimetypes', | |
77 | }); | |
78 | ||
29fa7feb SI |
79 | __PACKAGE__->register_method ({ |
80 | subclass => "PMG::API2::DestinationTLSPolicy", | |
81 | path => 'tlspolicy', | |
82 | }); | |
83 | ||
36069192 DM |
84 | __PACKAGE__->register_method ({ |
85 | name => 'index', | |
86 | path => '', | |
87 | method => 'GET', | |
88 | description => "Directory index.", | |
89 | parameters => { | |
90 | additionalProperties => 0, | |
a643bba6 | 91 | properties => {}, |
36069192 DM |
92 | }, |
93 | returns => { | |
94 | type => 'array', | |
95 | items => { | |
96 | type => "object", | |
97 | properties => { section => { type => 'string'} }, | |
98 | }, | |
99 | links => [ { rel => 'child', href => "{section}" } ], | |
100 | }, | |
101 | code => sub { | |
102 | my ($param) = @_; | |
103 | ||
104 | my $res = []; | |
105 | foreach my $section (@$section_type_enum) { | |
106 | push @$res, { section => $section }; | |
bdcc6f0f DM |
107 | } |
108 | ||
be6d6ffc | 109 | push @$res, { section => 'ldap' }; |
bef31f06 | 110 | push @$res, { section => 'mynetworks' }; |
0d0dc6b5 | 111 | push @$res, { section => 'mimetypes' }; |
62ebb4bc | 112 | push @$res, { section => 'users' }; |
5b2bb556 | 113 | push @$res, { section => 'domains' }; |
c3346bf1 | 114 | push @$res, { section => 'fetchmail' }; |
5ac6bd0e | 115 | push @$res, { section => 'cluster' }; |
bdcc6f0f | 116 | push @$res, { section => 'ruledb' }; |
3118b703 | 117 | push @$res, { section => 'transport' }; |
16fdeb84 | 118 | push @$res, { section => 'whitelist' }; |
b7f1924f | 119 | push @$res, { section => 'regextest' }; |
29fa7feb | 120 | push @$res, { section => 'tlspolicy' }; |
bdcc6f0f | 121 | |
36069192 DM |
122 | return $res; |
123 | }}); | |
124 | ||
be6e2db9 DM |
125 | my $api_read_config_section = sub { |
126 | my ($section) = @_; | |
36069192 | 127 | |
be6e2db9 | 128 | my $cfg = PMG::Config->new(); |
36069192 | 129 | |
1e3f960e | 130 | my $data = dclone($cfg->{ids}->{$section} // {}); |
be6e2db9 DM |
131 | $data->{digest} = $cfg->{digest}; |
132 | delete $data->{type}; | |
36069192 | 133 | |
be6e2db9 DM |
134 | return $data; |
135 | }; | |
ebad4fe3 | 136 | |
be6e2db9 DM |
137 | my $api_update_config_section = sub { |
138 | my ($section, $param) = @_; | |
ebad4fe3 | 139 | |
be6e2db9 DM |
140 | my $code = sub { |
141 | my $cfg = PMG::Config->new(); | |
142 | my $ids = $cfg->{ids}; | |
ebad4fe3 | 143 | |
be6e2db9 DM |
144 | my $digest = extract_param($param, 'digest'); |
145 | PVE::SectionConfig::assert_if_modified($cfg, $digest); | |
ebad4fe3 | 146 | |
be6e2db9 DM |
147 | my $delete_str = extract_param($param, 'delete'); |
148 | die "no options specified\n" | |
149 | if !$delete_str && !scalar(keys %$param); | |
150 | ||
151 | foreach my $opt (PVE::Tools::split_list($delete_str)) { | |
7c23fb04 | 152 | delete $ids->{$section}->{$opt}; |
be6e2db9 DM |
153 | } |
154 | ||
155 | my $plugin = PMG::Config::Base->lookup($section); | |
156 | my $config = $plugin->check_config($section, $param, 0, 1); | |
157 | ||
158 | foreach my $p (keys %$config) { | |
7c23fb04 | 159 | $ids->{$section}->{$p} = $config->{$p}; |
be6e2db9 DM |
160 | } |
161 | ||
162 | $cfg->write(); | |
c248d69f | 163 | |
c90f3170 | 164 | $cfg->rewrite_config(undef, 1); |
be6e2db9 DM |
165 | }; |
166 | ||
167 | PMG::Config::lock_config($code, "update config section '$section' failed"); | |
168 | }; | |
169 | ||
170 | foreach my $section (@$section_type_enum) { | |
171 | ||
be6e2db9 DM |
172 | my $plugin = PMG::Config::Base->lookup($section); |
173 | ||
174 | __PACKAGE__->register_method ({ | |
175 | name => "read_${section}_section", | |
176 | path => $section, | |
177 | method => 'GET', | |
753a1d32 | 178 | proxyto => 'master', |
54c55aa1 | 179 | permissions => { check => [ 'admin', 'audit' ] }, |
be6e2db9 DM |
180 | description => "Read $section configuration properties.", |
181 | parameters => { | |
182 | additionalProperties => 0, | |
183 | properties => {}, | |
184 | }, | |
185 | returns => { type => 'object' }, | |
186 | code => sub { | |
187 | my ($param) = @_; | |
188 | ||
189 | return $api_read_config_section->($section); | |
190 | }}); | |
191 | ||
192 | __PACKAGE__->register_method ({ | |
193 | name => "update_${section}_section", | |
194 | path => $section, | |
195 | method => 'PUT', | |
753a1d32 | 196 | proxyto => 'master', |
c248d69f | 197 | protected => 1, |
54c55aa1 | 198 | permissions => { check => [ 'admin' ] }, |
be6e2db9 DM |
199 | description => "Update $section configuration properties.", |
200 | parameters => $plugin->updateSchema(1), | |
201 | returns => { type => 'null' }, | |
202 | code => sub { | |
203 | my ($param) = @_; | |
204 | ||
205 | $api_update_config_section->($section, $param); | |
206 | ||
207 | return undef; | |
208 | }}); | |
209 | } | |
210 | ||
b7f1924f DC |
211 | __PACKAGE__->register_method({ |
212 | name => 'regextest', | |
213 | path => 'regextest', | |
214 | method => 'POST', | |
215 | protected => 0, | |
216 | permissions => { check => [ 'admin', 'qmanager', 'audit' ] }, | |
217 | description => "Test Regex", | |
218 | parameters => { | |
219 | additionalProperties => 0, | |
220 | properties => { | |
221 | regex => { | |
222 | type => 'string', | |
223 | description => 'The Regex to test', | |
224 | maxLength => 1024, | |
225 | }, | |
226 | text => { | |
227 | type => 'string', | |
228 | description => 'The String to test', | |
229 | maxLength => 1024, | |
230 | } | |
231 | }, | |
232 | }, | |
233 | returns => { | |
234 | type => 'number', | |
235 | }, | |
236 | code => sub { | |
237 | my ($param) = @_; | |
238 | ||
239 | my $text = $param->{text}; | |
240 | my $regex = $param->{regex}; | |
241 | ||
242 | my $regex_check = sub { | |
243 | my $start_time = [Time::HiRes::gettimeofday]; | |
244 | my $match = 0; | |
245 | if ($text =~ /$regex/) { | |
246 | $match = 1; | |
247 | } | |
248 | my $elapsed = Time::HiRes::tv_interval($start_time) * 1000; | |
249 | die "The Regular Expression '$regex' did not match the text '$text' (elapsed time: $elapsed ms)\n" | |
250 | if !$match; | |
251 | return $elapsed; | |
252 | }; | |
253 | ||
254 | my $elapsed = PVE::Tools::run_fork_with_timeout(2, $regex_check); | |
255 | if ($elapsed eq '') { | |
256 | die "The Regular Expression timed out\n"; | |
257 | } | |
258 | ||
259 | return $elapsed; | |
260 | }}); | |
bdcc6f0f | 261 | |
be6e2db9 | 262 | 1; |