DNSSEC key rollover updates

This commit is contained in:
Pinga 2025-03-11 18:32:05 +02:00
parent 44e975bf6e
commit d4a935055f
7 changed files with 70 additions and 247 deletions

View file

@ -1012,9 +1012,8 @@ class SystemController extends Controller
$secureTld = $tld['secure'];
if ($secureTld === 1) {
$tld_extension_cleaned = ltrim($tld['tld'], '.');
$zone = escapeshellarg($tld_extension_cleaned);
$statusOutput = shell_exec("rndc dnssec -status $zone");
$zone = ltrim($tld['tld'], '.');
$statusOutput = shell_exec("sudo rndc dnssec -status " . escapeshellarg($zone) . " 2>&1");
if (!$statusOutput) {
$dnssecData = ['error' => "Unable to fetch DNSSEC status for $zone."];
@ -1031,14 +1030,46 @@ class SystemController extends Controller
foreach ($matches as $match) {
$keyId = $match[1];
$algorithm = $match[2];
// Convert algorithm name to corresponding number for dnssec-dsfromkey
$algoMap = [
'RSASHA1' => '005', 'RSASHA1-NSEC3-SHA1' => '007',
'RSASHA256' => '008', 'RSASHA512' => '010',
'ECDSAP256SHA256' => '013', 'ECDSAP384SHA384' => '014',
'ED25519' => '015', 'ED448' => '016'
];
$algoNum = $algoMap[$algorithm] ?? '000'; // Default to unknown if missing
// Determine if key is active or in rollover state
$keyStatus = strpos($statusOutput, "key: $keyId") !== false
? (strpos($statusOutput, "key signing: yes") !== false ? 'Active' : 'Pending Rollover')
: 'Unknown';
preg_match("/key: $keyId.*?(?=\\nkey:|\\z)/s", $statusOutput, $keyBlockMatch);
$keyBlock = $keyBlockMatch[0] ?? '';
// Skip keys explicitly removed from the zone
if (strpos($keyBlock, 'Key has been removed from the zone') !== false) {
continue;
}
// Determine key status accurately
$keyStatus = strpos($keyBlock, 'key signing: yes') !== false ? 'Active' : 'Pending Rollover';
// Extract next rollover date
preg_match('/Next rollover scheduled on ([^\\n]+)/', $keyBlock, $rolloverMatch);
$nextRollover = $rolloverMatch[1] ?? null;
// Extract retirement date, if present
preg_match('/Key.*removed.*on ([^\\n]+)/', $keyBlock, $retirementMatch);
$retirementDate = $retirementMatch[1] ?? null;
// Extract published date
preg_match('/published:\s+yes\s+-\s+since\s+([^\n]+)/', $keyBlock, $publishedMatch);
$publishedDate = isset($publishedMatch[1]) ? trim($publishedMatch[1]) : null;
// Extract DS status ("rumoured" or "omnipresent")
preg_match('/- ds:\s+(\w+)/', $keyBlock, $dsMatch);
$dsStatus = $dsMatch[1] ?? null;
// Extract DS record for this key
$dsRecord = shell_exec("dnssec-dsfromkey -2 /var/lib/bind/K{$tld_extension_cleaned}.+008+{$keyId}.key");
$dsRecord = shell_exec("dnssec-dsfromkey -2 /var/lib/bind/K{$zone}.+{$algoNum}+{$keyId}.key");
$dsRecord = $dsRecord ? trim($dsRecord) : 'N/A';
// Append key details
@ -1048,6 +1079,10 @@ class SystemController extends Controller
'ds_record' => $dsRecord,
'status' => $keyStatus,
'timestamp' => date('Y-m-d H:i:s'),
'next_rollover' => $nextRollover,
'retirement_date' => $retirementDate,
'published_date' => $publishedDate,
'ds_status' => $dsStatus,
];
}

View file

@ -105,18 +105,16 @@
<table class="table table-vcenter card-table">
<thead>
<tr>
<th>{{ __('Key ID') }}</th>
<th>{{ __('Algorithm') }}</th>
<th>{{ __('DS Record') }}</th>
<th>{{ __('Status') }}</th>
<th>{{ __('Timestamp') }}</th>
<th>{{ __('Published') }}</th>
<th>{{ __('Next Rollover') }}</th>
<th>{{ __('Parent') }}</th>
</tr>
</thead>
<tbody>
{% for key in dnssecData.keys %}
<tr>
<td>{{ key.key_id }}</td>
<td>{{ key.algorithm }}</td>
<td>
{% if key.ds_record != 'N/A' %}
<p class="user-select-all tracking-wide mb-0">
@ -128,14 +126,30 @@
</td>
<td>
{% if key.status == 'Active' %}
<span class="badge bg-success">{{ __('Active') }}</span>
<span class="badge bg-success text-success-fg">{{ __('Active') }}</span>
{% elseif key.status == 'Pending Rollover' %}
<span class="badge bg-warning">{{ __('Pending Rollover') }}</span>
<span class="badge bg-warning text-warning-fg">{{ __('Pending Rollover') }}</span>
{% else %}
<span class="badge bg-secondary">{{ __('Unknown') }}</span>
<span class="badge bg-secondary text-secondary-fg">{{ __('Unknown') }}</span>
{% endif %}
</td>
<td>{{ key.timestamp }}</td>
<td>{{ key.published_date }}</td>
<td>{{ key.next_rollover }}</td>
<td>
{% if key.ds_status == 'omnipresent' %}
<span class="status-indicator status-green" title="DS record submitted and active at parent zone">
<span class="status-indicator-circle"></span>
</span>
{% elseif key.ds_status == 'rumoured' %}
<span class="status-indicator status-orange status-indicator-animated" title="DS record needs submission to parent zone">
<span class="status-indicator-circle"></span>
</span>
{% else %}
<span class="status-indicator status-gray" title="DS record status unknown or unavailable">
<span class="status-indicator-circle"></span>
</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>