Skip to content
This repository was archived by the owner on Nov 26, 2024. It is now read-only.

Add the ability to talk to Kong when the admin endpoint sits behind a self signed cert #54

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ if [[ ! -z "${TEST_CERT}" ]]; then
EXTRA_PARAMS="--test-cert"
fi;

if [[ ! -z "${ALLOW_SELF_SIGNED_CERT_KONG}" ]]; then
EXTRA_PARAMS="${EXTRA_PARAMS} --allow-self-signed-cert-kong"
fi;

exec /workdir/certbot-agent certs:update ${EXTRA_PARAMS} ${KONG_ENDPOINT} ${EMAIL} ${DOMAINS}
2 changes: 1 addition & 1 deletion src/Certbot/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
37 changes: 23 additions & 14 deletions src/Command/UpdateCertificatesCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -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",
);
}

Expand Down Expand Up @@ -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
Expand All @@ -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));
Expand Down
9 changes: 5 additions & 4 deletions src/Kong/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' => [
Expand All @@ -39,16 +39,17 @@ 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
// Any domain can be used on the endpoint, as they're aliased internally to the single
// 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();
Expand Down