mirror of
https://github.com/laravel/valet.git
synced 2026-02-05 16:40:05 +01:00
Merge pull request #1461 from adrum/feature/renew-certs
added the ability to renew certs and view their expiration dates
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Valet;
|
namespace Valet;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
use DomainException;
|
use DomainException;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use PhpFpm;
|
use PhpFpm;
|
||||||
@@ -435,6 +436,26 @@ public function secured(): array
|
|||||||
})->unique()->values()->all();
|
})->unique()->values()->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of the URLs with expiration dates that are currently secured.
|
||||||
|
*/
|
||||||
|
public function securedWithDates(): array
|
||||||
|
{
|
||||||
|
return collect($this->secured())->map(function ($site) {
|
||||||
|
|
||||||
|
$filePath = $this->certificatesPath() . '/' . $site . '.crt';
|
||||||
|
|
||||||
|
$expiration = $this->cli->run("openssl x509 -enddate -noout -in $filePath");
|
||||||
|
|
||||||
|
$expiration = str_replace('notAfter=', '', $expiration);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'site' => $site,
|
||||||
|
'exp' => new DateTime($expiration),
|
||||||
|
];
|
||||||
|
})->unique()->values()->all();
|
||||||
|
}
|
||||||
|
|
||||||
public function isSecured(string $site): bool
|
public function isSecured(string $site): bool
|
||||||
{
|
{
|
||||||
$tld = $this->config->read()['tld'];
|
$tld = $this->config->read()['tld'];
|
||||||
@@ -480,6 +501,20 @@ public function secure(string $url, ?string $siteConf = null, int $certificateEx
|
|||||||
$this->files->putAsUser($this->nginxPath($url), $siteConf);
|
$this->files->putAsUser($this->nginxPath($url), $siteConf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renews all domains with a trusted TLS certificate.
|
||||||
|
*/
|
||||||
|
public function renew($expireIn): void
|
||||||
|
{
|
||||||
|
collect($this->securedWithDates())->each(function ($row) use ($expireIn) {
|
||||||
|
$url = $this->domain($row['site']);
|
||||||
|
|
||||||
|
$this->secure($url, null, $expireIn);
|
||||||
|
|
||||||
|
info('The [' . $url . '] site has been secured with a fresh TLS certificate.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If CA and root certificates are nonexistent, create them and trust the root cert.
|
* If CA and root certificates are nonexistent, create them and trust the root cert.
|
||||||
*
|
*
|
||||||
|
|||||||
33
cli/app.php
33
cli/app.php
@@ -61,6 +61,7 @@ function (ConsoleCommandEvent $event) {
|
|||||||
output();
|
output();
|
||||||
DnsMasq::install(Configuration::read()['tld']);
|
DnsMasq::install(Configuration::read()['tld']);
|
||||||
output();
|
output();
|
||||||
|
Site::renew();
|
||||||
Nginx::restart();
|
Nginx::restart();
|
||||||
output();
|
output();
|
||||||
Valet::symlinkToUsersBin();
|
Valet::symlinkToUsersBin();
|
||||||
@@ -278,13 +279,33 @@ function (ConsoleCommandEvent $event) {
|
|||||||
/**
|
/**
|
||||||
* Display all of the currently secured sites.
|
* Display all of the currently secured sites.
|
||||||
*/
|
*/
|
||||||
$app->command('secured', function (OutputInterface $output) {
|
$app->command('secured [--expiring] [--days=]', function (OutputInterface $output, $expiring = null, $days = 60) {
|
||||||
$sites = collect(Site::secured())->map(function ($url) {
|
$now = (new Datetime())->add(new DateInterval('P' . $days . 'D'));
|
||||||
return ['Site' => $url];
|
$sites = collect(Site::securedWithDates())
|
||||||
});
|
->when($expiring, fn ($collection) => $collection->filter(fn ($row) => $row['exp'] < $now))
|
||||||
|
->map(function ($row) {
|
||||||
|
return [
|
||||||
|
'Site' => $row['site'],
|
||||||
|
'Valid Until' => $row['exp']->format('Y-m-d H:i:s T'),
|
||||||
|
];
|
||||||
|
})
|
||||||
|
->when($expiring, fn ($collection) => $collection->sortBy('Valid Until'));
|
||||||
|
|
||||||
table(['Site'], $sites->all());
|
return table(['Site', 'Valid Until'], $sites->all());
|
||||||
})->descriptions('Display all of the currently secured sites');
|
})->descriptions('Display all of the currently secured sites', [
|
||||||
|
'--expiring' => 'Limits the results to only sites expiring within the next 60 days.',
|
||||||
|
'--days' => 'To be used with --expiring. Limits the results to only sites expiring within the next X days. Default is set to 60.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renews all domains with a trusted TLS certificate.
|
||||||
|
*/
|
||||||
|
$app->command('renew [--expireIn=]', function (OutputInterface $output, $expireIn = 368) {
|
||||||
|
Site::renew($expireIn);
|
||||||
|
Nginx::restart();
|
||||||
|
})->descriptions('Renews all domains with a trusted TLS certificate.', [
|
||||||
|
'--expireIn' => 'The amount of days the self signed certificate is valid for. Default is set to "368"',
|
||||||
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an Nginx proxy config for the specified domain.
|
* Create an Nginx proxy config for the specified domain.
|
||||||
|
|||||||
@@ -436,7 +436,12 @@ public function test_secured_command()
|
|||||||
[$app, $tester] = $this->appAndTester();
|
[$app, $tester] = $this->appAndTester();
|
||||||
|
|
||||||
$site = Mockery::mock(RealSite::class);
|
$site = Mockery::mock(RealSite::class);
|
||||||
$site->shouldReceive('secured')->andReturn(['tighten.test']);
|
$site->shouldReceive('securedWithDates')->andReturn([
|
||||||
|
[
|
||||||
|
'site' => 'tighten.test',
|
||||||
|
'exp' => new DateTime('Aug 2 13:16:40 2024 GMT')
|
||||||
|
]
|
||||||
|
]);
|
||||||
swap(RealSite::class, $site);
|
swap(RealSite::class, $site);
|
||||||
|
|
||||||
$tester->run(['command' => 'secured']);
|
$tester->run(['command' => 'secured']);
|
||||||
@@ -445,6 +450,22 @@ public function test_secured_command()
|
|||||||
$this->assertStringContainsString('tighten.test', $tester->getDisplay());
|
$this->assertStringContainsString('tighten.test', $tester->getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_renew_command()
|
||||||
|
{
|
||||||
|
[$app, $tester] = $this->appAndTester();
|
||||||
|
|
||||||
|
$site = Mockery::mock(RealSite::class);
|
||||||
|
$site->shouldReceive('renew')->andReturn();
|
||||||
|
swap(RealSite::class, $site);
|
||||||
|
|
||||||
|
$nginx = Mockery::mock(Nginx::class);
|
||||||
|
$nginx->shouldReceive('restart')->once();
|
||||||
|
swap(Nginx::class, $nginx);
|
||||||
|
|
||||||
|
$tester->run(['command' => 'renew']);
|
||||||
|
$tester->assertCommandIsSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
public function test_proxy_command()
|
public function test_proxy_command()
|
||||||
{
|
{
|
||||||
[$app, $tester] = $this->appAndTester();
|
[$app, $tester] = $this->appAndTester();
|
||||||
|
|||||||
Reference in New Issue
Block a user