Sindbad~EG File Manager
<?php
namespace App\Command;
use Doctrine\ORM\EntityManagerInterface;
use GuzzleHttp\Client;
use O2switch\CpanelLib\Client\NginxVarnish;
use O2switch\CpanelLib\DataEntity\ApiVhost;
use O2switch\CpanelLib\DataEntity\NginxVarnishConfig;
use O2switch\CpanelLib\Entity\Customization;
use O2switch\CpanelLib\Entity\WafCustomization;
use O2switch\CpanelLib\Helper\ConfigHelper;
use O2switch\CpanelLib\Helper\ProxyInfo;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class IpxtenderSslChecker extends BaseCommand
{
/** @var EntityManagerInterface */
private $em;
protected static $defaultName = 'ipxtender:ssl-checker';
protected function configure(){
$this
->setDescription("Check for SSL certificates that are not up to date on ipxtender based on the local databases and SSL files.")
->setHelp("This command will loop over all local customization and check on ipxtender that the SSL is up-to-date. If not it will try to reinstall the certificate from the local file.")
->addOption('reinstall', null, InputOption::VALUE_OPTIONAL, "Set to 1 to try forcing reinstallating the domain on ipxtender to update the SSL", "0");
;
}
protected function execute(InputInterface $input, OutputInterface $output){
$reinstall = $input->getOption('reinstall') === 1 || $input->getOption('reinstall') === '1'
? true
: false;
if($reinstall){
if(file_exists('/usr/local/cpanel/share/o2switch-xtrem-cache/o2switch-xtrem-cache-code/config/prod.php')){
$tmp = include '/usr/local/cpanel/share/o2switch-xtrem-cache/o2switch-xtrem-cache-code/config/prod.php';
$ipxtenderConfig = $conf;
$configHelper = new ConfigHelper($ipxtenderConfig);
unset($conf, $tmp, $dbParams, $cmsRules, $ieOnFr, $plOnFr, $deOnFr, $nlOnFr, $ltOnFr, $czOnFr, $ptOnFr, $itOnFr,
$frOnFr, $beOnFr, $beOnFr, $esOnFr, $fiOnFr, $ukOnFr, $ipxtenderConfig);
$apiClient = new NginxVarnish(new Client(), $this->log);
} else {
$output->writeln(sprintf('<error>Cant use the reinstall option because the o2switch-xtrem-cache file is not accessible.</error>'));
return Command::FAILURE;
}
}
$customizations = $this->em->getRepository(Customization::class)->findAll();
if(!$this->apacheHttpdParser->parse($this->apacheHttpdConf)){
$output->writeln(sprintf('<error>Cant parse the httpd.conf !</error>'));
return Command::FAILURE;
}
$httpdData = $this->apacheHttpdParser->getData();
/**
* @var Customization $c
*/
foreach($customizations as $c){
if(!isset($c->getChains()[0]) || !is_string($c->getChains()[0]->getServerIp())){
$output->writeln(sprintf('<comment>Ignoring %s, cant retrieve the IP</comment>', $c->getMainDomain()));
continue;
}
if(!isset($httpdData[$c->getMainDomain()]['sslCertificateFilepath'])){
$output->writeln(sprintf('<comment>Ignoring %s, domain is not on the httpd.conf, probably deleted.</comment>', $c->getMainDomain()));
continue;
}
$info = $httpdData[$c->getMainDomain()];
if(empty($info['sslCertificateFilepath'])){
$output->writeln(sprintf('<comment>Ignoring %s, dont have a SSL installed.</comment>', $c->getMainDomain()));
continue;
}
$sslPath = $info['sslCertificateFilepath'];
if(!file_exists($sslPath)){
$output->writeln(sprintf('<comment>Ignoring %s %s dont exists</comment>', $c->getMainDomain(), $sslPath));
continue;
}
$cert = file_get_contents($sslPath);
if($cert === false){
$output->writeln(sprintf('<comment>Ignoring %s, cant open the SSL file %s</comment>', $c->getMainDomain(), $sslPath));
continue;
}
$cert = openssl_x509_parse($cert);
if($cert === false || !isset($cert['serialNumber'])){
$output->writeln(sprintf('<comment>Ignoring %s, cant parse the SSL file %s to retrieve the serialNumber</comment>', $c->getMainDomain(), $sslPath));
continue;
}
$ip = $c->getChains()[0]->getServerIp();
$domain = $c->getMainDomain();
$g = stream_context_create ([
"http" => [
'method' => 'HEAD'
],
'header' => [
'host' => $domain,
],
"ssl" => [
"capture_peer_cert" => true,
'SNI_enabled' => true,
'SNI_server_name' => $domain,
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
'CN_match' => $domain,
'disable_compression' => true,
"peer_name" => $domain
]
]);
try {
$r = stream_socket_client("ssl://$ip:443", $errno, $errstr, 5, STREAM_CLIENT_CONNECT, $g);
if($r === false){
throw new \Exception("stream_socket_client() returned false");
}
$params = stream_context_get_params($r);
fclose($r);
} catch (\Exception $e){
$output->writeln(sprintf('<comment>Ignoring %s, exception received %s</comment>', $c->getMainDomain(), $e->getMessage()));
continue;
}
if(!isset($params["options"]["ssl"]["peer_certificate"])){
$output->writeln(sprintf('<comment>Ignoring %s, cant retrieve SSL details</comment>', $c->getMainDomain()));
continue;
}
$installedCert = openssl_x509_parse($params["options"]["ssl"]["peer_certificate"]);
if($installedCert === false || !isset($installedCert['serialNumber'])){
$output->writeln(sprintf('<comment>Ignoring %s, cant parse the remote SSL to retrieve the serialNumber</comment>', $c->getMainDomain()));
continue;
}
if($installedCert['serialNumber'] === $cert['serialNumber']){
$output->writeln(sprintf('<info>%s seems OK. Expected %s == %s</info>', $c->getMainDomain(), $cert['serialNumber'], $installedCert['serialNumber']));
continue;
}
$output->writeln(sprintf('<comment>%s seems to have a fucked SSL certificate. Expected %s != %s</comment>', $c->getMainDomain(), $cert['serialNumber'], $installedCert['serialNumber']));
usleep(1000000);
if(!$reinstall){
continue;
}
continue;
// TODO
$apiVhost = (new ApiVhost())
->setSslKeyFile($this->data['data']['args']['key'] ?? null)
->setSslCrtFile($this->data['data']['args']['cert'] ?? null)
->setSslCaBundleFile(!empty($this->data['data']['args']['cabundle'] ?? null) ? $this->data['data']['args']['cabundle'] : null)
->setMainDomain($c->getMainDomain())
->setCpUser($c->getCpUser())
->setTemplateName('default')
->setAdditionalsParams($c->getAdditionalData())
->setDomainAliases('www.' . $c->getMainDomain())
->setIsSslAvailable(true)
->setOriginalBackendIp($c->getOriginalBackendIP())
->setListenToIp($c->getChains()[0]->getServerIp())
->setListenToPort(ProxyInfo::getIpxtenderProxyPassInfo($c, 'listenToPort'))
->setListenToSslPort(ProxyInfo::getIpxtenderProxyPassInfo($c, 'listenToSslPort'))
->setProxyPassIp(ProxyInfo::getIpxtenderProxyPassInfo($c, 'proxyPassIp'))
->setProxyPassPort(ProxyInfo::getIpxtenderProxyPassInfo($c, 'proxyPassPort'))
->setProxyPassProtocol(ProxyInfo::getIpxtenderProxyPassInfo($c, 'proxyPassProtocol'))
->setProxyPassSslIp(ProxyInfo::getIpxtenderProxyPassInfo($c, 'proxyPassSslIp'))
->setProxyPassSslPort(ProxyInfo::getIpxtenderProxyPassInfo($c, 'proxyPassSslPort'))
->setProxyPassSslProtocol(ProxyInfo::getIpxtenderProxyPassInfo($c, 'proxyPassSslProtocol'))
;
$wafCustomization = $this->em->getRepository(WafCustomization::class)->findOneBy([
'domain' => $domain,
'cpUser' => $c->getCpUser()
]);
if($wafCustomization instanceof WafCustomization){
$apiVhost->setAdditionalsParams(
is_array($apiVhost->getAdditionalsParams())
? array_merge($apiVhost->getAdditionalsParams(), ['wafCustomization' => $wafCustomization->getRules()])
: ['wafCustomization' => $wafCustomization->getRules()]
);
}
$serverId = $configHelper->getServerNameByIp($ip);
$nginxVarnishConfig = (new NginxVarnishConfig())
->setServerIp($configHelper->getServerMainIp($serverId))
->setPort($configHelper->getServerPort($serverId, 'nginx'))
->setToken($configHelper->getServerToken($serverId))
->setAlgo($configHelper->getServerAlgo($serverId))
->setSecretHash($configHelper->getServerSecret($serverId))
;
try {
$apiClient
->setConfig($nginxVarnishConfig)
->configureVhost('nginx', $apiVhost);
} catch (\Exception $e){
$output->writeln(sprintf('<comment>%s reinstalled on ipxtender</comment>', $domain));
continue;
}
$output->writeln(sprintf('<info>%s reinstalled on ipxtender', $domain));
}
return Command::SUCCESS;
}
/**
* @param string $cert
* @return null[]|string[]
*/
private function splitCombinedCertificates(string $cert) : array {
$key = null;
$crt = null;
$cabundle = null;
$i = 0;
foreach(explode("\n", $cert) as $line){
if (strpos($line, 'BEGIN RSA PRIVATE KEY') !== false) {
$mode = 'key';
} elseif (strpos($line, 'BEGIN CERTIFICATE') !== false) {
$mode = 'crt';
$i++;
}
if($mode === 'key'){
$key .= "$line\n";
} elseif ($mode === 'crt') {
if($i === 1){
$crt .= "$line\n";
} else {
$cabundle .= "$line\n";
}
}
}
return [$key, $crt, $cabundle];
}
/**
* @required
*/
public function setEm(EntityManagerInterface $em): void
{
$this->em = $em;
}
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists