diff --git a/README.md b/README.md index eb8b0db..d5d6fe1 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,14 @@ docker run -it --rm \ -e TEST_CERT=true \ phpdockerio/kong-certbot-agent +# Get a certificate for a single domain, and submit to kong +# Kong's admin API is behind a self-signed certificate +docker run -it --rm \ + -e KONG_ENDPOINT=http://kong-admin:8001 \ + -e EMAIL=foo@bar.com \ + -e DOMAINS=bar.com \ + -e ALLOW_SELF_SIGNED_CERT_KONG=true \ + phpdockerio/kong-certbot-agent ``` ## FAQ diff --git a/entrypoint.sh b/entrypoint.sh index 568c9bb..e6f6af3 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -5,4 +5,8 @@ if [[ ! -z "${TEST_CERT}" ]]; then EXTRA_PARAMS="--test-cert" fi; +if [[ ! -z "${ALLOW_SELF_SIGNED_CERT_KONG}" ]]; then + EXTRA_PARAMS="--allow-self-signed-cert-kong" +fi; + exec /workdir/certbot-agent certs:update ${EXTRA_PARAMS} ${KONG_ENDPOINT} ${EMAIL} ${DOMAINS} diff --git a/src/Certbot/Handler.php b/src/Certbot/Handler.php index cad2488..3b73e62 100644 --- a/src/Certbot/Handler.php +++ b/src/Certbot/Handler.php @@ -87,7 +87,7 @@ public function acquireCertificate(array $domains, string $email, bool $testCert } // Ensure certs are readable - $fullChain = file_get_contents($fullChainPath); + $fullChain = file_get_contents($fullChainPath); $privateKey = file_get_contents($privateKeyPath); return new Certificate( diff --git a/src/Command/UpdateCertificatesCommand.php b/src/Command/UpdateCertificatesCommand.php index 412e7d5..f776c64 100644 --- a/src/Command/UpdateCertificatesCommand.php +++ b/src/Command/UpdateCertificatesCommand.php @@ -56,25 +56,31 @@ protected function configure(): void $this ->setDescription('Requests certificates from Let\'s Encrypt for the given domains and notifies Kong') ->addArgument( - 'kong-endpoint', - InputArgument::REQUIRED, - 'Base URL to Kong Admin API; eg: https://foo:8001' + name: 'kong-endpoint', + mode: InputArgument::REQUIRED, + description: 'Base URL to Kong Admin API; eg: https://foo:8001' ) ->addArgument( - 'email', - InputArgument::REQUIRED, - 'Email the set of domains is to be associated with at Let\'s Encrypt' + name: 'email', + mode: InputArgument::REQUIRED, + description: 'Email the set of domains is to be associated with at Let\'s Encrypt' ) ->addArgument( - 'domains', - InputArgument::REQUIRED, - 'Comma separated list of domains to request certs for; eg: bar.com,foo.bar.com' + name: 'domains', + mode: InputArgument::REQUIRED, + description: 'Comma separated list of domains to request certs for; eg: bar.com,foo.bar.com' ) ->addOption( - 'test-cert', - 't', - InputOption::VALUE_NONE, - 'Require test certificate from staging-letsencrypt' + name: 'test-cert', + shortcut: 't', + mode: InputOption::VALUE_NONE, + description: 'Require test certificate from staging-letsencrypt' + ) + ->addOption( + name: 'allow-self-signed-cert-kong', + shortcut: '-s', + mode: InputOption::VALUE_NONE, + description: "Allow self signed certs in Kong's admin endpoint", ); } @@ -107,6 +113,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int /** @var bool $testCert */ $testCert = $input->getOption('test-cert'); + /** @var bool $allowSelfSignedCert */ + $allowSelfSignedCert = $input->getOption('allow-self-signed-cert-kong'); + $this->validateInput($email, $kongAdminUri, $domains); // Acquire certificates from certbot. This is not all-or-nothing, whatever certs we acquire come out here @@ -116,7 +125,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $certificate = $this->certbot->acquireCertificate($domains, $email, $testCert); // Store certs into kong via the admin UI. Again, not all-or-nothing - if ($this->kong->store($certificate, $kongAdminUri) === true) { + if ($this->kong->store($certificate, $kongAdminUri, $allowSelfSignedCert) === true) { $certOrCerts = count($certificate->getDomains()) > 1 ? 'Certificates' : 'Certificate'; $output->writeln(sprintf('%s for %s correctly sent to Kong', $certOrCerts, $outputDomains)); diff --git a/src/Kong/Handler.php b/src/Kong/Handler.php index 1cdf15e..73f7eac 100644 --- a/src/Kong/Handler.php +++ b/src/Kong/Handler.php @@ -28,7 +28,7 @@ public function __construct(private ClientInterface $guzzle) /** * Stores the given certificate in Kong. */ - public function store(Certificate $certificate, string $kongAdminUri): bool + public function store(Certificate $certificate, string $kongAdminUri, bool $allowSelfSignedCert): bool { $payload = [ 'headers' => [ @@ -39,6 +39,7 @@ public function store(Certificate $certificate, string $kongAdminUri): bool 'key' => $certificate->getKey(), 'snis' => $certificate->getDomains(), ], + 'verify' => !$allowSelfSignedCert, ]; // From Kong 0.14, they finally fixed PUT as UPSERT @@ -46,9 +47,9 @@ public function store(Certificate $certificate, string $kongAdminUri): bool // certificate object within Kong try { $this->guzzle->request( - 'put', - sprintf('%s/certificates/%s', $kongAdminUri, $certificate->getDomains()[0]), - $payload + method: 'put', + uri: sprintf('%s/certificates/%s', $kongAdminUri, $certificate->getDomains()[0]), + options: $payload, ); } catch (BadResponseException $ex) { $request = $ex->getRequest();