#!/usr/bin/env perl

# https://documentation.cpanel.net/display/SDK/Tutorial+-+Call+UAPI%27s+SSL%3A%3Ainstall_ssl+Function+in+Custom+Code

# Return errors if Perl experiences problems.
use strict;
use warnings;

# Allow my code to perform web requests.
use LWP::UserAgent;
use LWP::Protocol::https;
# Use the correct encoding to prevent wide character warnings.
use Encode;
use utf8;
# Properly decode JSON.
use JSON;
# Function properly with Base64 authentication headers.
use MIME::Base64;

### ----- CHANGEME - BEGIN ----

# Authentication information.
my $username    = 'YOUR-USERNAME-HERE';
my $password    = 'YOUR-PASSWORD-HERE';
my $domain      = 'YOUR-DOMAIN-HERE';
my $cpanel_host = 'YOUR-CPANEL-HOST-HERE'; # NOTE: Your cPanel host name may, or may not, be the same as your domain name.

# Files for certificate and domain key
my $cert_file =  '/PATH/TO/YOUR/CRT/FILE';        # YOUR-DOMAIN.crt
my $key_file  =  '/PATH/TO/YOUR/DOMAIN/KEY/FILE'; # YOUR-DOMAIN.key

### ----- CHANGEME - END ------

# The URL for the SSL::install_ssl UAPI function.
# Cpanel secure port number is always 2083.
my $request = 'https://' . $cpanel_host . ':2083/execute/SSL/install_ssl';

# Required to allow HTTPS connections to unsigned services.
# Services on localhost are always unsigned.
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

# Create a useragent object.
my $ua = LWP::UserAgent->new();

# Add authentication headers.
$ua->default_header(
  'Authorization' => 'Basic ' . MIME::Base64::encode("$username:$password"),
);

# Read in the SSL certificate and key file.
my ( $key, $cert );
{
    local $/;
    open ( my $fh, '<', $key_file ) or die "Cannot open file $key_file: $!\n";;
    $key = <$fh>;
    close $key;

    open ( $fh, '<', $cert_file ) or die "Cannot open file $cert_file: $!\n";
    $cert = <$fh>;
    close $fh;
}

# Make the call.
my $response = $ua->post($request,
    Content_Type => 'form-data',
    Content => [
        domain => $domain,
        key    => $key,
        cert   => $cert,
    ],
);

###print "DEBUG ", $response->decoded_content;

# Create an object to decode the JSON.
# Sorted by keys and pretty-printed.
my $json_printer = JSON->new->pretty->canonical(1);

# UTF-8 encode before decoding to avoid wide character warnings.
my $content = JSON::decode_json(Encode::encode_utf8($response->decoded_content));

# Print output, UTF-8 encoded to avoid wide character warnings.
print Encode::encode_utf8($json_printer->encode($content));
