]>
Commit | Line | Data |
---|---|---|
19407634 | 1 | #!/usr/bin/perl |
aff192e6 DM |
2 | |
3 | use strict; | |
19407634 DM |
4 | use warnings; |
5 | ||
aff192e6 DM |
6 | use IO::File; |
7 | use File::Find; | |
8 | use File::stat; | |
9 | ||
5366e88e | 10 | use PVE::APLInfo; |
4a57db55 FG |
11 | use PVE::CertHelpers; |
12 | use PVE::Certificate; | |
784a50cc | 13 | use PVE::Cluster::Setup; |
5366e88e | 14 | use PVE::Cluster; |
3ac3653e | 15 | use PVE::DataCenterConfig; |
5366e88e TL |
16 | use PVE::INotify; |
17 | use PVE::NodeConfig; | |
4027c59b | 18 | use PVE::RPCEnvironment; |
5366e88e | 19 | use PVE::SafeSyslog; |
784a50cc | 20 | use PVE::Tools; |
5366e88e | 21 | |
4a57db55 | 22 | use PVE::API2::ACME; |
5366e88e TL |
23 | use PVE::API2::APT; |
24 | use PVE::API2::Subscription; | |
4027c59b | 25 | |
c8969ecb | 26 | initlog ('pveupdate', 'daemon'); |
aff192e6 | 27 | |
4027c59b DM |
28 | die "please run as root\n" if $> != 0; |
29 | ||
30 | $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin'; | |
31 | ||
32 | PVE::INotify::inotify_init(); | |
33 | ||
34 | my $rpcenv = PVE::RPCEnvironment->init('cli'); | |
35 | ||
36 | $rpcenv->init_request(); | |
37 | $rpcenv->set_language($ENV{LANG}); | |
c9355915 | 38 | $rpcenv->set_user('root@pam'); |
4027c59b DM |
39 | |
40 | my $nodename = PVE::INotify::nodename(); | |
41 | ||
42 | eval { PVE::API2::Subscription->update({ node => $nodename }); }; | |
43 | if (my $err = $@) { | |
a88002cf | 44 | syslog ('err', "update subscription info failed: $err"); |
4027c59b DM |
45 | } |
46 | ||
c9164975 DM |
47 | my $dccfg = PVE::Cluster::cfs_read_file('datacenter.cfg'); |
48 | eval { PVE::APLInfo::update($dccfg->{http_proxy}); }; | |
49 | if (my $err = $@) { | |
a88002cf DM |
50 | syslog ('err', "update appliance info failed - see /var/log/pveam.log for details"); |
51 | } | |
52 | ||
d017de1f | 53 | my $info = eval { PVE::API2::Subscription::read_etc_subscription() }; |
8432c6d3 TL |
54 | |
55 | my $notify_on = $dccfg->{notify}->{'package-updates'} // 'auto'; | |
56 | my $notify = 0; | |
57 | if ($notify_on eq 'auto') { | |
58 | # hosts with subscriptions are likely production system and thus want infos about new packages | |
59 | $notify = ($info && $info->{status} eq 'active') ? 1 : 0; | |
60 | } elsif ($notify_on eq 'always') { | |
61 | $notify = 1; | |
62 | } elsif ($notify_on eq 'never') { | |
63 | $notify = 0; | |
64 | } else { | |
65 | warn "unexpected package-updates notify configuration value '$notify_on'\n"; | |
66 | } | |
d916c09d DM |
67 | eval { PVE::API2::APT->update_database({ node => $nodename, notify => $notify, quiet => 1 }); }; |
68 | if (my $err = $@) { | |
69 | syslog ('err', "update apt database failed: $err"); | |
c9164975 | 70 | } |
aff192e6 | 71 | |
4a57db55 FG |
72 | eval { |
73 | my $node_config = PVE::NodeConfig::load_config($nodename); | |
e7083f9a FG |
74 | my $acme_node_config = PVE::NodeConfig::get_acme_conf($node_config); |
75 | if ($acme_node_config && $acme_node_config->{domains}) { | |
4a57db55 FG |
76 | my $cert = PVE::CertHelpers::cert_path_prefix($nodename).".pem"; |
77 | if (-e $cert) { | |
78 | if (PVE::Certificate::check_expiry($cert, time() + 30*24*60*60)) { | |
79 | PVE::API2::ACME->renew_certificate({ node => $nodename }); | |
80 | } else { | |
81 | syslog ('info', 'Custom certificate does not expire soon, skipping ACME renewal.'); | |
82 | } | |
83 | } else { | |
84 | syslog ('info', 'ACME config found for node, but no custom certificate exists. Skipping ACME renewal until initial certificate has been deployed.'); | |
85 | } | |
86 | } | |
87 | }; | |
88 | syslog ('err', "Renewing ACME certificate failed: $@") if $@; | |
89 | ||
784a50cc DC |
90 | eval { |
91 | my $certpath = PVE::CertHelpers::default_cert_path_prefix($nodename).".pem"; | |
92 | my $capath = "/etc/pve/pve-root-ca.pem"; | |
93 | ||
75456ef3 FG |
94 | my $renew = sub { |
95 | my ($msg) = @_; | |
96 | ||
784a50cc DC |
97 | # get CA info |
98 | my $cainfo = PVE::Certificate::get_certificate_info($capath); | |
99 | ||
100 | # get cert and check issuer and chain metadata | |
101 | my $certinfo = PVE::Certificate::get_certificate_info($certpath); | |
102 | if ($certinfo->{issuer} ne $cainfo->{subject}) { | |
f5ad0c97 | 103 | die "SSL certificate ($certpath) is not issued by root CA ($capath)!\n"; |
784a50cc DC |
104 | } |
105 | ||
106 | # check if cert is really signed by the ca | |
f5ad0c97 | 107 | # TODO: replace by low level ssleay interface if version 1.86 is available |
784a50cc DC |
108 | PVE::Tools::run_command(['/usr/bin/openssl', 'verify', '-CAfile', $capath, $certpath]); |
109 | ||
75456ef3 | 110 | print "PVE certificate $msg\n"; |
784a50cc DC |
111 | # create new certificate |
112 | my $ip = PVE::Cluster::remote_node_ip($nodename); | |
113 | PVE::Cluster::Setup::gen_pve_ssl_cert(1, $nodename, $ip); | |
f5ad0c97 | 114 | |
784a50cc DC |
115 | print "Restarting pveproxy after renewing certificate\n"; |
116 | PVE::Tools::run_command(['systemctl', 'reload-or-restart', 'pveproxy']); | |
75456ef3 FG |
117 | }; |
118 | ||
119 | if (PVE::Certificate::check_expiry($certpath, time() + 14*24*60*60)) { | |
120 | # expires in next 2 weeks | |
121 | $renew->("expires soon, renewing..."); | |
122 | } elsif (!PVE::Certificate::check_expiry($certpath, time() + 2*365*24*60*60)) { | |
123 | # expires in more than 2 years | |
e33f43a3 | 124 | $renew->("expires in more than 2 years, renewing to reduce certificate life-span for client compatibility..."); |
784a50cc DC |
125 | } |
126 | }; | |
127 | syslog ('err', "Checking/Renewing SSL certificate failed: $@") if $@; | |
128 | ||
aff192e6 DM |
129 | sub cleanup_tasks { |
130 | ||
131 | my $taskdir = "/var/log/pve/tasks"; | |
132 | my $filename = "$taskdir/index.1"; | |
133 | ||
134 | my $fh = IO::File->new($filename, O_RDONLY); | |
135 | return if !$fh; | |
136 | ||
137 | my $endtime = 0; | |
138 | while (defined(my $line = <$fh>)) { | |
139 | if ($line =~ m/^(\S+)(\s([0-9A-Za-z]{8})(\s(\S.*))?)?$/) { | |
140 | $endtime = hex($3); | |
141 | last; | |
142 | } | |
143 | } | |
144 | close($fh); | |
145 | ||
146 | return if !$endtime; | |
147 | ||
148 | # print "delete task older that $endtime\n" . localtime($endtime) . "\n"; | |
149 | ||
150 | my $count = 0; | |
151 | ||
152 | my $wanted = sub { | |
153 | my $filename = $_; | |
154 | ||
155 | return if $filename !~ m/^UPID:/; | |
156 | ||
157 | my $st; | |
158 | if (($st = stat($filename)) && ($st->mtime < $endtime)) { | |
159 | unlink($filename); | |
160 | $count++; | |
161 | } | |
162 | }; | |
163 | ||
b0a65294 | 164 | foreach my $subdir (qw(0 1 2 3 4 5 6 7 8 9 A B C D E F)) { |
aff192e6 DM |
165 | my $path = "$taskdir/$subdir"; |
166 | find($wanted, $path); | |
167 | } | |
168 | ||
169 | if ($count) { | |
170 | syslog('info', "cleanup removed $count task logs"); | |
171 | } | |
172 | } | |
173 | ||
174 | cleanup_tasks(); | |
175 | ||
176 | exit (0); |