Viewing File: /usr/local/cpanel/whostmgr/docroot/cgi/ncssl/source/src/Service/CpanelHelper.php

<?php

namespace App\Service;

use App\Service\CpanelApi\CpanelApi;
use App\Service\NcPlugin\PluginException;
use Psr\Log\LoggerInterface;

class CpanelHelper
{
    public const PRIVATE_KEY_NAME = 'nc_module_key_';

    public function __construct(
        private readonly CpanelApi $api,
        private readonly LoggerInterface $cpanelLogger,
    ) {
    }

    /**
     * @return array
     * @throws PluginException
     */
    public function getDomainsList(): array
    {
        $api_resp = $this->api->uapiCall('DomainInfo', 'list_domains');
        $domains = array_merge(
            $api_resp['addon_domains'],
            $api_resp['sub_domains'],
            [$api_resp['main_domain']]
        );

        sort($domains);

        return $domains;
    }

    /**
     * @param $domain
     * @return mixed|null
     * @throws PluginException
     */
    public function getDomainDocRoot($domain): mixed
    {
        $api_resp = $this->api->uapiCall('DomainInfo', 'single_domain_data', array('domain' => $domain));

        return $api_resp['documentroot'];
    }

    /**
     * @param $domain
     *
     * @return mixed|null
     */
    public function getInstalledSsl($domain): mixed
    {
        try {
            $api_resp = $this->api->uapiCall('SSL', 'installed_hosts');
        } catch (PluginException $e) {
            $this->cpanelLogger->error('Can\'t get installed SSL certificates. Error: ' . $e->getMessage());

            return null;
        }


        $hosts = $api_resp->getData();

        foreach ($hosts as $host) {
            if (in_array($domain, $host['domains'], true)) {
                return $host['certificate']['id'];
            }
        }

        return null;
    }

    /**
     * @return array|mixed
     * @throws PluginException
     */
    public function getPrivateKeys(): mixed
    {
        $api_resp = $this->api->uapiCall('SSL', 'list_keys');
        $pks = $api_resp->getData();
        if (!is_array($pks)) {
            //TODO Partially log retrieved data.
            $pks = [];
        }

        return $pks;
    }

    /**
     * @return array
     * @throws PluginException
     */
    public function getSslDomains(): array
    {
        $api_resp = $this->api->uapiCall('SSL', 'installed_hosts');

        $hosts = $api_resp->getData();
        $domains = array();

        foreach ($hosts as $host) {
            $host_domains = array();
            foreach ($host['domains'] as $row) {
                $host_domains[$host['certificate']['id']] = $row;
            }

            $domains = array_merge($domains, $host_domains);
        }

        return $domains;
    }

    /**
     * @return bool
     * @throws PluginException
     */
    public function isSniSupported(): bool
    {
        $api_resp = $this->api->uapiCall('SSL', 'is_sni_supported');

        if ($api_resp->getData() == '1') {
            return true;
        } else {
            return false;
        }
    }

    /**
     * This method retrieves a boolean value that indicates dedicated IP on server.
     *
     * @return bool - true if we have dedicated IP or false in other case
     */
    public function checkDedicatedIP(): bool
    {
        $pos = strpos(file_get_contents("/etc/domainips"), $_SERVER["DOMAIN"]);
        if ($pos === false) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * @param $privateKeyId
     * @param array $data
     * @return mixed|null
     * @throws PluginException
     */
    public function generateCsr($privateKeyId, array $data): mixed
    {
        $data = array_map('trim', $data);

        //Validate data
        $required_fields = array('domains', 'countryName', 'stateOrProvinceName', 'localityName', 'organizationName');
        foreach ($required_fields as $field) {
            if (empty($data[$field])) {
                throw new PluginException('Wrong csr request data. Missed "' . $field . '" field.');
            }
        }

        $data['key_id'] = $privateKeyId;

        $api_resp = $this->api->uapiCall('SSL', 'generate_csr', $data);

        $csr = $api_resp['text'];

        $this->api->uapiCall('SSL', 'delete_csr', array('id' => $api_resp['id']));

        return $csr;
    }

    /**
     * @param $id
     * @return string|null
     * @throws PluginException
     */
    public function getPrivateKey($id): ?string
    {
        $api_resp = $this->api->uapiCall('SSL', 'show_key', ['id' => $id]);

        $key_data = $api_resp->getData();

        return $key_data['key'] ?? null;
    }

    public function getPrivateKeyId($friendlyName)
    {
        $privateKeyId = null;
        try {
            $response = $this->api->uapiCall('SSL', 'show_key', ['friendly_name' => $friendlyName]);
            $privateKeyData = $response->getData();
            if (isset($privateKeyData['details']['id'])) {
                $privateKeyId = $privateKeyData['details']['id'];
            }

        } catch (PluginException $e) {
            $this->cpanelLogger->error('Couldn\'t get private key by friendly_name:"' . $friendlyName . '". Error:' . $e->getMessage());
        }

        return $privateKeyId;
    }

    /**
     * @param $ncCertificateId
     * @return string
     */
    public function generatePrivateKeyFriendlyName($ncCertificateId): string
    {
        return self::PRIVATE_KEY_NAME . $ncCertificateId;
    }

    /**
     * @param $friendly_name
     * @return bool|mixed|null
     * @throws PluginException
     */
    public function generatePrivateKey($friendly_name): mixed
    {
        $privateKeyFriendlyName = self::PRIVATE_KEY_NAME . $friendly_name;

        $api_resp = $this->api->uapiCall('SSL', 'generate_key', array(
            'friendly_name' => $privateKeyFriendlyName,
            'keysize' => 2048,
        ));

        $key_id = $api_resp['id'];

        if (empty($key_id)) {
            throw new PluginException("Can't generate key #{$friendly_name}. Private key id is empty");
        }

        return $key_id;
    }

    /**
     * @param $id
     * @param $friendly_name
     * @throws PluginException
     */
    public function renamePrivateKey($id, $friendly_name): void
    {
        $this->api->uapiCall('SSL', 'set_key_friendly_name', array(
            'id' => $id,
            'new_friendly_name' => self::PRIVATE_KEY_NAME . $friendly_name,
        ));
    }

    /**
     * This method installs an SSL certificate on specified domain.
     *
     * @param string $domain - The domain onto whose website for which to install the certificate.
     * @param string $cert - certificate body
     * @param string $key_id - private key ID
     * @param string $cabundle - CA bundle body
     * @param string $friendly_name - certificate friendly name
     * @return array - ["cert_id", "key_id"]
     *@throws PluginException
     */
    public function installSsl(string $domain, string $cert, string $key_id, string $cabundle = '', string $friendly_name = ''): array
    {
        try {
            $private_key = $this->getPrivateKey($key_id);
        } catch (PluginException $e) {
            $this->cpanelLogger->error('get Private Key Error', [
                'key' => $key_id,
                'domain' => $domain,
                'error' => $e->getMessage(),
            ]);
            throw new PluginException('Can\'t find private key for cert in cPanel.');
        }

        $apiParams = array(
            'domain' => $domain,
            'cert' => $cert,
            'key' => $private_key
        );

        if ($cabundle !== '') {
            $apiParams['cabundle'] = $cabundle;
        }

        $api_resp = $this->api->uapiCall('SSL', 'install_ssl', $apiParams);

        if ($friendly_name !== '') {
            $this->api->uapiCall('SSL', 'set_cert_friendly_name', [
                'id' => $api_resp['cert_id'],
                'new_friendly_name' => $friendly_name,
            ]);
        }

        $this->renamePrivateKey($api_resp['key_id'], $friendly_name);

        return [
            'cert_id' => $api_resp['cert_id'],
            'key_id' => $api_resp['key_id'],
        ];
    }

    /**
     * @param $id
     * @return array
     * @throws PluginException
     */
    public function getCertInfo($id): array
    {
        $api_resp = $this->api->uapiCall('SSL', 'fetch_cert_info', array('id' => $id));
        $cert_data = $api_resp->getData();

        $api_resp2 = $this->api->uapiCall('SSL', 'fetch_key_and_cabundle_for_certificate', array('certificate' => $cert_data['certificate']));

        return array(
            'certificate' => $cert_data['certificate'],
            'private_key' => $cert_data['key'],
            'is_self_signed' => $cert_data['is_self_signed'] === 1,
            'cabundle' => (stripos($cert_data['cabundle'], 'sorry') !== false ? $cert_data['cabundle'] : ''),
            'domains' => $api_resp2['domain'],
        );
    }

    /**
     * This method will uninstall SSL from the website indicated by the specified domain.
     *
     * @param string $domain - The domain from whose website from which you wish to uninstall SSL
     * @throws PluginException
     */
    public function deleteSslHost(string $domain): void
    {
        $this->api->uapiCall('SSL', 'delete_ssl', array('domain' => $domain));
    }

    /**
     * This method deletes the SSL certificate from the account.
     *
     * @param string $id - cPanel certificate ID
     * @throws PluginException
     */
    public function deleteCertificate(string $id): void
    {
        $this->api->uapiCall('SSL', 'delete_cert', array('id' => $id));
    }

    /**
     * @return CpanelApi
     */
    public function getCpApiModel(): CpanelApi
    {
        return $this->api;
    }
}
Back to Directory File Manager