]> git.proxmox.com Git - pve-common.git/blobdiff - src/PVE/Certificate.pm
network: replace system() with run_command()
[pve-common.git] / src / PVE / Certificate.pm
index b0b9bbfd714564a4a60399c1c90a3ddcc5a91840..5bc9848f15bbe7cf13eb05b16272358267bfba49 100644 (file)
@@ -54,17 +54,20 @@ PVE::JSONSchema::register_standard_option('pve-certificate-info', {
        notbefore => {
            type => 'integer',
            description => 'Certificate\'s notBefore timestamp (UNIX epoch).',
+           renderer => 'timestamp',
            optional => 1,
        },
        notafter => {
            type => 'integer',
            description => 'Certificate\'s notAfter timestamp (UNIX epoch).',
+           renderer => 'timestamp',
            optional => 1,
        },
        san => {
            type => 'array',
            description => 'List of Certificate\'s SubjectAlternativeName entries.',
            optional => 1,
+           renderer => 'yaml',
            items => {
                type => 'string',
            },
@@ -75,6 +78,16 @@ PVE::JSONSchema::register_standard_option('pve-certificate-info', {
            format => 'pem-certificate',
            optional => 1,
        },
+       'public-key-type' => {
+           type => 'string',
+           description => 'Certificate\'s public key algorithm',
+           optional => 1,
+       },
+       'public-key-bits' => {
+           type => 'integer',
+           description => 'Certificate\'s public key size',
+           optional => 1,
+       },
     },
 });
 
@@ -203,6 +216,20 @@ sub convert_asn1_to_epoch {
     return Date::Parse::str2time($iso_time);
 }
 
+sub get_certificate_fingerprint {
+    my ($cert_path) = @_;
+
+    my $cert = $read_certificate->($cert_path);
+
+    my $fp = Net::SSLeay::X509_get_fingerprint($cert, 'sha256');
+    Net::SSLeay::X509_free($cert);
+
+    die "unable to get fingerprint for '$cert_path' - got empty value\n"
+       if !defined($fp) || $fp eq '';
+
+    return $fp;
+}
+
 sub get_certificate_info {
     my ($cert_path) = @_;
 
@@ -257,6 +284,14 @@ sub get_certificate_info {
     $info->{san} = $parse_san->(Net::SSLeay::X509_get_subjectAltNames($cert));
     $info->{pem} = Net::SSLeay::PEM_get_string_X509($cert);
 
+    my $pub_key = eval { Net::SSLeay::X509_get_pubkey($cert) };
+    warn $@ if $@;
+    if ($pub_key) {
+       $info->{'public-key-type'} = Net::SSLeay::OBJ_nid2sn(Net::SSLeay::EVP_PKEY_id($pub_key));
+       $info->{'public-key-bits'} = Net::SSLeay::EVP_PKEY_bits($pub_key);
+       Net::SSLeay::EVP_PKEY_free($pub_key);
+    }
+
     Net::SSLeay::X509_free($cert);
 
     $cert_path =~ s!^.*/!!g;
@@ -301,6 +336,9 @@ sub generate_csr {
     my $san = [ map { $_->{value} } grep { $_->{type} eq 'dns' } @$identifiers ];
     die "DNS identifiers are required to generate a CSR.\n" if !scalar @$san;
 
+    # optional
+    my $common_name = delete($attr{common_name}) // $san->[0];
+
     my $md = eval { Net::SSLeay::EVP_get_digestbyname($dig_alg) };
     die "Invalid digest algorithm '$dig_alg'\n" if !$md;
 
@@ -331,7 +369,7 @@ sub generate_csr {
        }
     };
 
-    $add_name_entry->('CN', @$san[0]);
+    $add_name_entry->('CN', $common_name);
     for (qw(C ST L O OU)) {
         if (defined(my $v = $attr{$_})) {
            $add_name_entry->($_, $v);