Add support to get certificate chain as separate certificates

- https://github.com/afosto/yaac/issues/10
- The purpose is to support web servers such as apache < 2.4.8
  where the intermediate certificate needs to be separate
- Add method Helper::splitCertificate to parse cert chain
- Add param to Certificate::getCertificate($asChain = true)
  to maintain bc and get the certificate with or without chain
- Add method Certificate::getIntermediateCertificate to get just
  the intermediate certificate
This commit is contained in:
Michael Munger
2020-04-24 16:36:49 -06:00
parent e654975374
commit 713285f8b5
2 changed files with 46 additions and 5 deletions

View File

@@ -17,6 +17,16 @@ class Certificate
*/ */
protected $certificate; protected $certificate;
/**
* @var string
*/
protected $certificateNoChain;
/**
* @var string
*/
protected $intermediateCertificate;
/** /**
* @var string * @var string
*/ */
@@ -39,6 +49,7 @@ class Certificate
$this->privateKey = $privateKey; $this->privateKey = $privateKey;
$this->csr = $csr; $this->csr = $csr;
$this->certificate = $certificate; $this->certificate = $certificate;
list($this->certificateNoChain, $this->intermediateCertificate) = Helper::splitCertificate($certificate);
$this->expiryDate = Helper::getCertExpiryDate($certificate); $this->expiryDate = Helper::getCertExpiryDate($certificate);
} }
@@ -64,9 +75,18 @@ class Certificate
* Return the certificate as a multi line string * Return the certificate as a multi line string
* @return string * @return string
*/ */
public function getCertificate(): string public function getCertificate($asChain = true): string
{ {
return $this->certificate; return $asChain ? $this->certificate : $this->certificateNoChain;
}
/**
* Return the intermediate certificate as a multi line string
* @return string
*/
public function getIntermediateCertificate(): string
{
return $this->intermediateCertificate;
} }
/** /**

View File

@@ -65,7 +65,7 @@ class Helper
/** /**
* Get a new CSR * Get a new CSR
* *
* @param array $domains * @param array $domains
* @param $key * @param $key
* *
* @return string * @return string
@@ -81,8 +81,8 @@ class Helper
'[v3_req]', '[v3_req]',
'[v3_ca]', '[v3_ca]',
'[SAN]', '[SAN]',
'subjectAltName=' . implode(',', array_map(function ($domain) { 'subjectAltName='.implode(',', array_map(function ($domain) {
return 'DNS:' . $domain; return 'DNS:'.$domain;
}, $domains)), }, $domains)),
]; ];
@@ -138,4 +138,25 @@ class Helper
return $accountDetails; return $accountDetails;
} }
/**
* Split a two certificate bundle into separate
* multi line string certificates
* @return array
*/
public static function splitCertificate(string $certificate): array
{
preg_match('/^(?<signed>-----BEGIN CERTIFICATE-----.+?-----END CERTIFICATE-----)\n'
.'(?<intermediate>-----BEGIN CERTIFICATE-----.+?-----END CERTIFICATE-----)$/s',
$certificate, $certificates);
$signed = $certificates['signed'] ?? null;
$intermediate = $certificates['intermediate'] ?? null;
if (!$signed || !$intermediate) {
throw new \Exception('Could not parse certificate string');
}
return [$signed, $intermediate];
}
} }