2022-09-26

用 DNS Record 驗證 Let's Encrypt 後打包丟給 Web Server 提供下載 Part-2

本系列共三篇:

用 DNS Record 驗證 Let's Encrypt 後打包丟給 Web Server 提供下載 Part-1
用 DNS Record 驗證 Let's Encrypt 後打包丟給 Web Server 提供下載 Part-2
用 DNS Record 驗證 Let's Encrypt 後打包丟給 Web Server 提供下載 Part-3

承上一篇 用 DNS Record 驗證 Let's Encrypt 後打包丟給 Web Server 提供下載 Part-1

本篇是 Web Server 提供手動下載的階段

WebRoot/Cert/config.php

#--------------------------------------------------------------------------------

<?php
// -----
$Domain = 'contoso.com';
$CertPackagesPath = 'C:/WebSite/z_CertPackage/';
$APIKey = 'lsiMwjc80ptrSoqvBHkTCIYGA6gaxDd7';
#All
$CertManager['UserName1'][]='all';
$CertManager['UserName2'][]='all';
#User
$CertManager['UserName3'][]='www';
$CertManager['UserName4'][]='webmail';
// -----
if (!isset($CertManager)) {
CloseConnection();
exit;
};

// -----
$DateTimeString = date("Ymd_His");
// -----
$CertManager = array_change_key_case_recursive($CertManager,CASE_LOWER);
$CertManager = array_map('nestedLowercase', $CertManager);
// -----
function array_change_key_case_recursive($Array) {
    return array_map(function($item) {
        if(is_array($item)) {
            $item = array_change_key_case_recursive($item);
};
        return $item;
    },array_change_key_case($Array));
};
function nestedLowercase($value) {
    if (is_array($value)) {
        return array_map('nestedLowercase', $value);
    };
    return strtolower($value);
};

#--------------------------------------------------------------------------------

WebRoot/Cert/index.php

#--------------------------------------------------------------------------------

<?php
if (!function_exists('CloseConnection')) {
include($_SERVER['DOCUMENT_ROOT'].'/API/Cert/Config.php');
};
require_once($_SERVER['DOCUMENT_ROOT'].'/AuthProcess.php');

include('Config.php');

// Check Permission
$ContinueConnection = False;
if (isset($CertManager)) {
if (in_array($GLOBALS['UserName'],array_keys($CertManager))) {
$ContinueConnection = True;
};
};
if (!$ContinueConnection) {
CloseConnection();
exit;
};
// Check Permission

if ( (!isset($GetCertPrivateKey)) || (!isset($GetCertPublicKey)) ) {
include($_SERVER['DOCUMENT_ROOT'].'/API/Cert/Config.php');
};

$CertPackages = array_diff(scandir($CertPackagesPath), array('.', '..'));

$LastPackages = array();
foreach ($CertPackages as $CertPackage) {
if (substr($CertPackage, -3) != '.7z') {
Continue;
};
$Cert = explode('_',$CertPackage);
$CertExpireDateTime = substr($Cert[1],0,4).'-'.substr($Cert[1],4,2).'-'.substr($Cert[1],6,2).' '.substr($Cert[2],0,2).':'.substr($Cert[2],2,2).':'.substr($Cert[2],4,2);
$CertExpireTimestamp = strtotime(substr($Cert[1],0,4).'-'.substr($Cert[1],4,2).'-'.substr($Cert[1],6,2).' '.substr($Cert[2],0,2).':'.substr($Cert[2],2,2).':'.substr($Cert[2],4,2));
if (isset($LastPackages[$Cert[0]]['ExpireDateTime'])) {
if ($CertExpireTimestamp > $LastPackages[$Cert[0]]['ExpireDateTime']) {
$LastPackages[$Cert[0]]['FileName'] = $CertPackage;
$LastPackages[$Cert[0]]['CertExpireDateTime'] = $CertExpireDateTime;
$LastPackages[$Cert[0]]['ExpireDateTimestamp'] = $CertExpireTimestamp ;
};
} else {
$LastPackages[$Cert[0]]['FileName'] = $CertPackage;
$LastPackages[$Cert[0]]['CertExpireDateTime'] = $CertExpireDateTime;
$LastPackages[$Cert[0]]['ExpireDateTimestamp'] = $CertExpireTimestamp ;
};
};

$LastPackages = array_change_key_case_recursive($LastPackages,CASE_LOWER);
$LastPackages = array_map('nestedLowercase', $LastPackages);

if(isset($_GET['d'])) {
$DownloadFile = '';
foreach (array_keys($LastPackages) as $CertHead) {
if ($_GET['d'] == $CertHead) {
if ( (in_array($CertHead,$CertManager[$GLOBALS['UserName']])) || (in_array('all',$CertManager[$GLOBALS['UserName']])) ) {
$DownloadFile = $LastPackages[$CertHead]['filename'];
break;
};
};
};
if ($DownloadFile == '') {
CloseConnection();
exit;
} else {
ob_clean();
$FP = fopen($CertPackagesPath.$DownloadFile,"r");
$FileSize = filesize($CertPackagesPath.$DownloadFile);
header('Content-Type: application/octet-stream');
header("Accept-Ranges:bytes");
header("Accept-Length:".$FileSize);
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" . $DownloadFile . "\"");
$Buffer=1024;
$BufferCount=0;
while (!feof($FP) && ($FileSize - $BufferCount) > 0) {
$Data = fread($FP,$Buffer);
$BufferCount = $Buffer;
echo $Data;
};
fclose($FP);
};

exit;
};

$TableBody = '';
$CertIndex = 0;
foreach (array_keys($LastPackages) as $CertHead) {
if ( (in_array($CertHead,$CertManager[$GLOBALS['UserName']])) || (in_array('all',$CertManager[$GLOBALS['UserName']])) ) {
$CertHeadShow = $CertHead;
if ($CertHead == 'wildcard') {
$CertHeadShow = '*';
};
$NowTimestamp = time();
$interval = seconds2human($LastPackages[$CertHead]['expiredatetimestamp']-$NowTimestamp); 
$Color = '#008000';
if ((int)$interval['d'] < 60) {
$Color = '#0909FF';
};
if ((int)$interval['d'] < 30) {
$Color = '#6C2DC7';
};
if ((int)$interval['d'] < 15) {
$Color = '#FF0000';
};

$TableBody .= '<tr style="Color:'.$Color.'"><td id="CertName_'.$CertIndex.'" align="center">'.$CertHeadShow.'.'.$Domain.'</td><td align="center">'.$LastPackages[$CertHead]['certexpiredatetime'].' ('.$interval['d'].'d, '.$interval['h'].':'.$interval['m'].':'.$interval['s'].')</td><td><button onclick="DownloadCert(\''.$CertHead.'\')" type="button">Download</button></td><td><input type="text" size="10" id="AuthCode_'.$CertIndex.'" value="'.myEncrypt($CertHead, $GetCertPrivateKey).'" onclick="CopyAPI(\''.$CertIndex.'\')" style="font-size:12px;cursor:hand;height:20px;width:80px;padding:0px;border: none;border-bottom: 1px solid red;outline: none;" readonly></td></tr>';
};

$CertIndex++;
};
$Table = '<table><tr><th width="150">FQDN</th><th>Expire Date (残り時間)</th><th>Download</th><th>AuthCode</th></tr>'.$TableBody.'</table>';

?>

<script type='text/javascript' src='/js/jquery-3.5.1.min.js'></script>
<script>
function DownloadCert(CertHead) {
var file_path = '?d='+CertHead;
var a = document.createElement('A');
a.href = file_path;
a.download = file_path.substr(file_path.lastIndexOf('/') + 1);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
function CopyAPI(CertIndex) {

var KeyValue = $('#AuthCode_' + CertIndex).val();

$('#AuthCode_' + CertIndex).select();
document.execCommand("copy");
alert('\r\nAuth Code of [ ' + $('#CertName_' + CertIndex).text() + ' ] has being Copied to Clipboard\r\n\r\nOnly for using in Get Cert Script');

$('#AuthCode_' + CertIndex).prop('selectionStart', 0).prop('selectionEnd',0).blur();
};
</script>

<?php

echo '<p><a href="/">Back to Web Root</a></p>';

echo 'Hi '.$GLOBALS['UserName'].',<br><br>Now: '.date('Y-m-d H:i:s',$NowTimestamp).'<br><br>';

echo $Table;
exit;

function seconds2human($ss) {
$Return['s'] = str_pad($ss%60,2,"0",STR_PAD_LEFT);
$Return['m'] = str_pad(floor(($ss%3600)/60),2,"0",STR_PAD_LEFT);
$Return['h'] = str_pad(floor(($ss%86400)/3600),2,"0",STR_PAD_LEFT);
$Return['d'] = str_pad(floor($ss/86400),2,"0",STR_PAD_LEFT);


return $Return;
}

Function myEncrypt($Data, $EncryptKey) {
$AESBlockSize = 128;
$iv = RandomPassword(($AESBlockSize/8));
$Encrypted = openssl_encrypt($Data, 'aes-256-cbc', $EncryptKey, 0, $iv);
return base64_encode($iv.$Encrypted);
};

Function RandomPassword($PasswordLength=16) {
$Alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$Password = Array();
$AlphaLength = strlen($Alphabet) - 1;
for ($i = 0; $i < $PasswordLength; $i++) {
$Password[] = $Alphabet[(rand(0, $AlphaLength))];
};
return implode($Password);
};
?>

#--------------------------------------------------------------------------------

註: 因為有做 Integrated Windows Authentication with Apache 2.4 on Windows
所以前面有動用一個 AuthProcess.php 來取得登入資訊

#--------------------------------------------------------------------------------

<?php
if (!function_exists('CloseConnection')) {
include($_SERVER['DOCUMENT_ROOT'].'/API/Cert/Config.php');
};

$Cred = explode('\\',$_SERVER['PHP_AUTH_USER']);
if (count($Cred) != 2) {
CloseConnection();
exit;
};

List($GLOBALS['UserDomain'], $GLOBALS['UserName']) = $Cred;
$GLOBALS['UserDomain'] = strtolower($GLOBALS['UserDomain']);
$GLOBALS['UserName'] = strtolower($GLOBALS['UserName']);

?>

#--------------------------------------------------------------------------------

沒有留言:

張貼留言