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