Compare commits

..

No commits in common. "d3f2533565c1fbc372e1d7018a5661e133d8c902" and "d013124c12012846e464d9d319cec3306fa22e0f" have entirely different histories.

4 changed files with 7 additions and 110 deletions

View File

@ -1 +1 @@
1.3.74
1.3.73

View File

@ -22,17 +22,18 @@ class CertificateSweep
/**
* Die Namen aus der Umgebung in die Liste übernehmen.
*
* Anlegen und aktualisieren, nie löschen: ein Name, der aus der Umgebung
* verschwindet, bleibt als Zeile stehen. Sein Zertifikat läuft ja weiter,
* und ein Eintrag, der still verschwindet, ist genau das Gegenteil einer
* Übersicht.
*
* @return int wie viele Zeilen neu hinzugekommen sind
*/
public function sync(): int
{
$bekannt = KnownHostnames::all();
$this->pruneVanished($bekannt);
$added = 0;
foreach ($bekannt as $hostname => $purpose) {
foreach (KnownHostnames::all() as $hostname => $purpose) {
$existing = ProxyHost::query()->where('hostname', $hostname)->first();
if ($existing === null) {
@ -58,41 +59,6 @@ class CertificateSweep
return $added;
}
/**
* Zeilen, die aus der Umgebung kamen und dort nicht mehr stehen.
*
* Zwei Fälle, und sie brauchen zwei Antworten:
*
* - Die Zeile hatte NIE ein Zertifikat. Dann war sie ein Fehlgriff so
* kam `127.0.0.1` aus `ADMIN_HOSTS` in die Liste, wo eine nackte IP als
* Wiederzugang stehen darf, für die es aber nie ein Zertifikat geben
* wird. Sie geht weg; ein dauerhaft roter Eintrag, den niemand beheben
* kann, macht die Übersicht unlesbar.
* - Die Zeile HAT ein Zertifikat. Dann wird sie zu einem Eintrag von Hand,
* statt zu verschwinden. Das Zertifikat läuft ja weiter, und etwas mit
* einer laufenden Frist still aus einer Übersicht zu nehmen ist das
* Gegenteil einer Übersicht der Betreiber entfernt sie selbst.
*
* @param array<string, string> $bekannt
*/
private function pruneVanished(array $bekannt): void
{
$verschwunden = ProxyHost::query()
->where('source', 'config')
->whereNotIn('hostname', array_keys($bekannt))
->get();
foreach ($verschwunden as $host) {
if ($host->hasCertificate()) {
$host->forceFill(['source' => 'manual'])->save();
continue;
}
$host->delete();
}
}
/** @return array{checked: int, failing: int} */
public function check(): array
{

View File

@ -59,27 +59,6 @@ final class KnownHostnames
return;
}
// KEINE IP-Adressen.
//
// `ADMIN_HOSTS` darf ausdrücklich eine nackte IP führen — sie ist der
// Wiederzugang zur Konsole, wenn ein Name einmal nicht auflöst. Aber für
// eine IP stellt Let's Encrypt kein Zertifikat aus, also steht sie in
// einer Zertifikatsübersicht nur als dauerhaft roter Eintrag, den
// niemand beheben kann.
//
// Der erste Filter verlangte bloß einen Punkt — `127.0.0.1` hat drei.
// Deshalb hier beides: die Adressprüfung UND die Bedingung, dass die
// letzte Marke keine Zahl ist. Eine Endung ist nie numerisch, und das
// fängt auch die Formen ab, die `FILTER_VALIDATE_IP` durchlässt.
if (filter_var($host, FILTER_VALIDATE_IP) !== false) {
return;
}
$letzteMarke = substr($host, strrpos($host, '.') + 1);
if ($letzteMarke === '' || ctype_digit($letzteMarke)) {
return;
}
// Konsole gewinnt gegen öffentlich, wenn ein Name in beiden Listen
// steht: die engere Aussage ist die richtige.
if (($found[$host] ?? null) !== 'console') {

View File

@ -198,51 +198,3 @@ it('counts what is valid, what expires soon and what is broken', function () {
->and($summary['soon'])->toBe(1)
->and($summary['failing'])->toBe(1);
});
/**
* Der Fund vom Live-Server: `127.0.0.1` stand in der Übersicht, als Konsole,
* mit „Kein gültiges Zertifikat: Connection refused".
*
* Er kam aus `ADMIN_HOSTS`, wo eine nackte IP als Wiederzugang ausdrücklich
* stehen darf. Der erste Filter verlangte nur einen Punkt davon hat
* `127.0.0.1` drei. Für eine IP stellt Let's Encrypt kein Zertifikat aus, also
* war das ein dauerhaft roter Eintrag, den niemand beheben kann.
*/
it('keeps IP addresses out of a certificate overview', function () {
config()->set('admin_access.hosts', ['admin.clupilot.com', '127.0.0.1', '2001:db8::1', '198.51.100.7']);
$gefunden = array_keys(App\Support\KnownHostnames::all());
expect($gefunden)->toContain('admin.clupilot.com')
->and($gefunden)->not->toContain('127.0.0.1')
->and($gefunden)->not->toContain('198.51.100.7')
->and($gefunden)->not->toContain('2001:db8::1');
});
/**
* Und die Zeile, die schon in der Datenbank steht, geht beim nächsten Abgleich
* weg sonst bliebe mein Fehler auf jeder Installation stehen, die einmal
* aktualisiert hat.
*/
it('clears out a config row that should never have been there', function () {
$ip = ProxyHost::create(['hostname' => '127.0.0.1', 'purpose' => 'console', 'source' => 'config']);
proxyPage();
expect(ProxyHost::query()->whereKey($ip->id)->exists())->toBeFalse();
});
/**
* Aber nichts mit laufendem Zertifikat verschwindet still. Es wird zu einem
* Eintrag von Hand, den der Betreiber selbst entfernt eine Frist, die weiter
* läuft, gehört nicht wortlos aus einer Übersicht genommen.
*/
it('turns a vanished name with a live certificate into a manual entry', function () {
$alt = ProxyHost::create(['hostname' => 'frueher.clupilot.com', 'purpose' => 'public', 'source' => 'config']);
$alt->forceFill(['certificate_expires_at' => now()->addDays(40), 'certificate_checked_at' => now()])->save();
proxyPage();
expect($alt->fresh()->isFromConfig())->toBeFalse()
->and(ProxyHost::query()->whereKey($alt->id)->exists())->toBeTrue();
});