mirror of
https://git.proxmox.com/git/pve-manager
synced 2025-06-14 20:07:42 +00:00
use certificate cache from PVE::Cluster package
This commit is contained in:
parent
5a7b4a74e7
commit
a947498513
@ -25,6 +25,7 @@ use PVE::SafeSyslog;
|
|||||||
use PVE::INotify;
|
use PVE::INotify;
|
||||||
use PVE::RPCEnvironment;
|
use PVE::RPCEnvironment;
|
||||||
use PVE::REST;
|
use PVE::REST;
|
||||||
|
use PVE::Cluster;
|
||||||
|
|
||||||
use Net::IP;
|
use Net::IP;
|
||||||
use URI;
|
use URI;
|
||||||
@ -105,95 +106,6 @@ sub get_login_formatter {
|
|||||||
return $info->{func};
|
return $info->{func};
|
||||||
}
|
}
|
||||||
|
|
||||||
my $cert_cache_nodes = {};
|
|
||||||
my $cert_cache_timestamp = time();
|
|
||||||
my $cert_cache_fingerprints = {};
|
|
||||||
sub update_cert_cache {
|
|
||||||
my ($update_node, $clear) = @_;
|
|
||||||
|
|
||||||
syslog('info', "Clearing outdated entries from certificate cache")
|
|
||||||
if $clear;
|
|
||||||
$cert_cache_timestamp = time() if !defined($update_node);
|
|
||||||
|
|
||||||
my $node_list = defined($update_node) ? [ $update_node ] : [ keys %$cert_cache_nodes ];
|
|
||||||
|
|
||||||
foreach my $node (@$node_list) {
|
|
||||||
my $clear_old = sub {
|
|
||||||
if (my $old_fp = $cert_cache_nodes->{$node}) {
|
|
||||||
# distrust old fingerprint
|
|
||||||
delete $cert_cache_fingerprints->{$old_fp};
|
|
||||||
# ensure reload on next proxied request
|
|
||||||
delete $cert_cache_nodes->{$node};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
my $err;
|
|
||||||
my $cert_path = "/etc/pve/nodes/$node/pve-ssl.pem";
|
|
||||||
my $custom_cert_path = "/etc/pve/nodes/$node/pveproxy-ssl.pem";
|
|
||||||
$cert_path = $custom_cert_path if -f $custom_cert_path;
|
|
||||||
my $cert;
|
|
||||||
eval {
|
|
||||||
my $bio = Net::SSLeay::BIO_new_file($cert_path, 'r');
|
|
||||||
$cert = Net::SSLeay::PEM_read_bio_X509($bio);
|
|
||||||
Net::SSLeay::BIO_free($bio);
|
|
||||||
};
|
|
||||||
$err = $@;
|
|
||||||
if ($err || !defined($cert)) {
|
|
||||||
&$clear_old() if $clear;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $fp;
|
|
||||||
eval {
|
|
||||||
$fp = Net::SSLeay::X509_get_fingerprint($cert, 'sha256');
|
|
||||||
};
|
|
||||||
$err = $@;
|
|
||||||
if ($err || !defined($fp) || $fp eq '') {
|
|
||||||
&$clear_old() if $clear;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $old_fp = $cert_cache_nodes->{$node};
|
|
||||||
$cert_cache_fingerprints->{$fp} = 1;
|
|
||||||
$cert_cache_nodes->{$node} = $fp;
|
|
||||||
|
|
||||||
if (defined($old_fp) && $fp ne $old_fp) {
|
|
||||||
delete $cert_cache_fingerprints->{$old_fp};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub check_cert_fingerprint {
|
|
||||||
my ($cert) = @_;
|
|
||||||
|
|
||||||
# clear cache every 30 minutes at least
|
|
||||||
update_cert_cache(undef, 1) if time() - $cert_cache_timestamp >= 60*30;
|
|
||||||
|
|
||||||
# get fingerprint of server certificate
|
|
||||||
my $fp;
|
|
||||||
eval {
|
|
||||||
$fp = Net::SSLeay::X509_get_fingerprint($cert, 'sha256');
|
|
||||||
};
|
|
||||||
return 0 if $@ || !defined($fp) || $fp eq ''; # error
|
|
||||||
|
|
||||||
my $check = sub {
|
|
||||||
for my $expected (keys %$cert_cache_fingerprints) {
|
|
||||||
return 1 if $fp eq $expected;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
return 1 if &$check();
|
|
||||||
|
|
||||||
# clear cache and retry at most once every minute
|
|
||||||
if (time() - $cert_cache_timestamp >= 60) {
|
|
||||||
syslog ('info', "Could not verify remote node certificate '$fp' with list of pinned certificates, refreshing cache");
|
|
||||||
update_cert_cache();
|
|
||||||
return &$check();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# server implementation
|
# server implementation
|
||||||
|
|
||||||
@ -702,13 +614,12 @@ sub proxy_request {
|
|||||||
# we don't care about intermediate or root certificates
|
# we don't care about intermediate or root certificates
|
||||||
return 1 if $depth != 0;
|
return 1 if $depth != 0;
|
||||||
# check server certificate against cache of pinned FPs
|
# check server certificate against cache of pinned FPs
|
||||||
return check_cert_fingerprint($cert);
|
return PVE::Cluster::check_cert_fingerprint($cert);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
# load and cache cert fingerprint if first time we proxy to this node
|
# load and cache cert fingerprint if first time we proxy to this node
|
||||||
update_cert_cache($node)
|
PVE::Cluster::initialize_cert_cache($node);
|
||||||
if defined($node) && !defined($cert_cache_nodes->{$node});
|
|
||||||
|
|
||||||
my $w; $w = http_request(
|
my $w; $w = http_request(
|
||||||
$method => $target,
|
$method => $target,
|
||||||
|
Loading…
Reference in New Issue
Block a user