|
28 | 28 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | 29 | */ |
30 | 30 |
|
31 | | -class letsencrypt_cli extends cli |
32 | | -{ |
33 | | - |
34 | | - function __construct() |
35 | | - { |
36 | | - $cmd_opt = []; |
37 | | - $cmd_opt['letsencrypt'] = 'showHelp'; |
38 | | - $cmd_opt['letsencrypt:list'] = 'list'; |
| 31 | +class letsencrypt_cli extends cli { |
| 32 | + |
| 33 | + function __construct() { |
| 34 | + $cmd_opt = []; |
| 35 | + $cmd_opt['letsencrypt'] = 'showHelp'; |
| 36 | + $cmd_opt['letsencrypt:list'] = 'listCertificates'; |
| 37 | + $cmd_opt['letsencrypt:info'] = 'outputCertificate'; |
39 | 38 | $cmd_opt['letsencrypt:cleanup-expired'] = 'cleanupExpired'; |
40 | 39 | $this->addCmdOpt($cmd_opt); |
41 | 40 | } |
42 | 41 |
|
43 | | - public function list($arg) |
44 | | - { |
| 42 | + public function listCertificates($arg) { |
45 | 43 | global $app; |
46 | 44 | $app->uses('letsencrypt'); |
47 | | - $certificates = $app->letsencrypt->get_certificate_list(); |
48 | | - foreach ($certificates as $certificate) { |
49 | | - print_r($certificate); |
| 45 | + $certificates = $this->getCertificates(); |
| 46 | + if(empty($certificates)) { |
| 47 | + return; |
| 48 | + } |
| 49 | + $table = [['type', 'id', 'valid info', 'serial', 'domains']]; |
| 50 | + $ansi_reset = "\033[0m"; |
| 51 | + $bold_red = "\033[1m\033[31m"; |
| 52 | + $bold_green = "\033[1m\033[32m"; |
| 53 | + foreach($certificates as $certificate) { |
| 54 | + $valid = ($certificate['is_valid'] ? ($bold_green . 'yes' . $ansi_reset) : ($bold_red . 'no ' . $ansi_reset)) . ' ' . $this->getValidInfo($certificate); |
| 55 | + $table[] = [ |
| 56 | + $certificate['signature_type'], |
| 57 | + $certificate['id'], |
| 58 | + $valid, |
| 59 | + $certificate['serial_number'], |
| 60 | + $this->getList($certificate['domains']), |
| 61 | + ]; |
50 | 62 | } |
| 63 | + $this->outputTable($table, ['variable_columns' => '1,4', 'expand' => true]); |
51 | 64 | } |
52 | 65 |
|
53 | | - public function cleanupExpired($arg) |
54 | | - { |
| 66 | + public function outputCertificate($args) { |
55 | 67 | global $app; |
| 68 | + if(empty($args)) { |
| 69 | + |
| 70 | + } |
| 71 | + if(empty($args)) { |
| 72 | + $this->swriteln('error: ID of the certificate is missing'); |
| 73 | + $this->showHelp($args); |
| 74 | + exit(1); |
| 75 | + } |
56 | 76 | $app->uses('letsencrypt'); |
57 | | - $removals = 0; |
58 | | - $hasErrors = false; |
59 | | - $certificates = $app->letsencrypt->get_certificate_list(); |
60 | | - foreach ($certificates as $certificate) { |
61 | | - if (! $certificate['is_valid']) { |
62 | | - $this->swriteln("Removing ".join(', ', $certificate['domains'])." expired certificate..."); |
63 | | - if ($app->letsencrypt->remove_certificate($certificate)) { |
64 | | - $removals += 1; |
65 | | - } else { |
66 | | - $this->swriteln("Could not remove ".print_r($certificate, true)); |
67 | | - $hasErrors = true; |
| 77 | + $certificates = $this->getCertificates(); |
| 78 | + if(empty($certificates)) { |
| 79 | + return; |
| 80 | + } |
| 81 | + foreach($args as $id) { |
| 82 | + $certificate = false; |
| 83 | + foreach($certificates as $c) { |
| 84 | + if($c['id'] == $id) { |
| 85 | + $certificate = $c; |
| 86 | + break; |
68 | 87 | } |
69 | 88 | } |
| 89 | + if($certificate) { |
| 90 | + $ansi_reset = "\033[0m"; |
| 91 | + $bold_red = "\033[1m\033[31m"; |
| 92 | + $bold_green = "\033[1m\033[32m"; |
| 93 | + $bold_yellow = "\033[1m\033[33m"; |
| 94 | + $gray = "\033[38;5;7m"; |
| 95 | + $valid = ($certificate['is_valid'] ? ($bold_green . 'yes' . $ansi_reset) : ($bold_red . 'no ' . $ansi_reset)) . ' ' . $this->getValidInfo($certificate); |
| 96 | + $table = [ |
| 97 | + ['key', 'value'], |
| 98 | + ['id', $certificate['id']], |
| 99 | + ['serial', $certificate['serial_number']], |
| 100 | + ['type', $certificate['signature_type']], |
| 101 | + ['valid', $valid . "\n" . $gray . 'from ' . $ansi_reset . $certificate['valid_from']->format('Y-m-d H:i:s') . "\n" . $gray . 'to ' . $ansi_reset . $certificate['valid_to']->format('Y-m-d H:i:s')], |
| 102 | + ['revokation', $certificate['is_revoked'] === null ? ($bold_yellow . 'not checked' . $ansi_reset) : $certificate['is_revoked'] ? ($bold_red . 'REVOKED' . $ansi_reset) : ($bold_green . 'not revoked' . $ansi_reset)], |
| 103 | + ['domains', $this->getList($certificate['domains'])], |
| 104 | + ['subject', $this->getAssocArray($certificate['subject'])], |
| 105 | + ['issuer', $this->getAssocArray($certificate['issuer'])], |
| 106 | + ['source', $certificate['source']], |
| 107 | + ['conf', $certificate['conf']], |
| 108 | + ['files', $this->getAssocArray($certificate['cert_paths'])], |
| 109 | + ]; |
| 110 | + $this->outputTable($table, ['min_lengths' => [10], 'variable_columns' => '1', 'expand' => true]); |
| 111 | + } else { |
| 112 | + $this->swriteln("\n" . 'Certificate not found: ' . $id . "\n"); |
| 113 | + } |
70 | 114 | } |
71 | | - if ($removals) { |
72 | | - $this->swriteln("Removed $removals expired certificates"); |
73 | | - } else { |
74 | | - $this->swriteln("No certificates were removed"); |
| 115 | + |
| 116 | + } |
| 117 | + |
| 118 | + public function cleanupExpired($arg) { |
| 119 | + global $app; |
| 120 | + $app->uses('letsencrypt'); |
| 121 | + $removals = 0; |
| 122 | + $hasErrors = false; |
| 123 | + $certificates = $this->getCertificates(); |
| 124 | + if(empty($certificates)) { |
| 125 | + return; |
| 126 | + } |
| 127 | + $certificates_to_remove = []; |
| 128 | + foreach($certificates as $certificate) { |
| 129 | + if(!$certificate['is_valid']) { |
| 130 | + $certificates_to_remove[] = $certificate; |
| 131 | + } |
| 132 | + } |
| 133 | + if(empty($certificates_to_remove)) { |
| 134 | + $this->swriteln('No expired certificates found'); |
| 135 | + return; |
75 | 136 | } |
76 | | - if ($hasErrors) { |
| 137 | + $ansi_reset = "\033[0m"; |
| 138 | + $bold_red = "\033[1m\033[31m"; |
| 139 | + $table = [['type', 'id', 'valid info', 'serial', 'domains']]; |
| 140 | + foreach($certificates_to_remove as $certificate) { |
| 141 | + $valid = $this->getValidInfo($certificate); |
| 142 | + $table[] = [ |
| 143 | + $certificate['signature_type'], |
| 144 | + $certificate['id'], |
| 145 | + $valid, |
| 146 | + $certificate['serial_number'], |
| 147 | + $this->getList($certificate['domains']), |
| 148 | + ]; |
| 149 | + } |
| 150 | + $this->outputTable($table, ['variable_columns' => '1,4', 'expand' => true]); |
| 151 | + $this->swriteln(''); |
| 152 | + if($this->simple_query($bold_red . 'Do you want to delete the certificates?' . $ansi_reset, ['yes', 'no'], 'no') == 'no') { |
| 153 | + $this->swriteln('No certificates were removed'); |
| 154 | + return; |
| 155 | + } |
| 156 | + foreach($certificates_to_remove as $certificate) { |
| 157 | + $this->swriteln('Removing expired certificate ' . $certificate['id']); |
| 158 | + if($app->letsencrypt->remove_certificate($certificate)) { |
| 159 | + $removals += 1; |
| 160 | + } else { |
| 161 | + $this->swriteln("Could not remove " . print_r($certificate, true)); |
| 162 | + $hasErrors = true; |
| 163 | + } |
| 164 | + } |
| 165 | + $this->swriteln('Removed ' . $removals . ' expired certificates'); |
| 166 | + if($hasErrors) { |
77 | 167 | exit(1); |
78 | 168 | } |
79 | 169 | } |
80 | 170 |
|
81 | | - public function showHelp($arg) |
82 | | - { |
| 171 | + public function showHelp($arg) { |
83 | 172 | global $conf; |
84 | 173 |
|
85 | 174 | $this->swriteln("---------------------------------"); |
86 | | - $this->swriteln("- Available commandline option -"); |
| 175 | + $this->swriteln("- Available commandline options -"); |
87 | 176 | $this->swriteln("---------------------------------"); |
88 | 177 | $this->swriteln("ispc letsencrypt list - lists all known certificates"); |
| 178 | + $this->swriteln("ispc letsencrypt info <id> - outputs all information of one certificate"); |
89 | 179 | $this->swriteln("ispc letsencrypt cleanup-expired - Cleanup all expired certificates."); |
90 | 180 | $this->swriteln("---------------------------------"); |
91 | 181 | $this->swriteln(); |
92 | 182 | } |
93 | 183 |
|
| 184 | + |
| 185 | + private function getList($array) { |
| 186 | + return join("\n", array_map(function($line) { |
| 187 | + $ansi_reset = "\033[0m"; |
| 188 | + $gray = "\033[38;5;7m"; |
| 189 | + return $gray . '• ' . $ansi_reset . $line; |
| 190 | + }, $array)); |
| 191 | + } |
| 192 | + |
| 193 | + private function getAssocArray($array) { |
| 194 | + return join("\n", array_map(function($key, $value) { |
| 195 | + $ansi_reset = "\033[0m"; |
| 196 | + $gray = "\033[38;5;7m"; |
| 197 | + return $gray . $key . '=' . $ansi_reset . $value; |
| 198 | + }, array_keys($array), array_values($array))); |
| 199 | + } |
| 200 | + |
| 201 | + private function getValidInfo($certificate) { |
| 202 | + $ansi_reset = "\033[0m"; |
| 203 | + $bold_red = "\033[1m\033[31m"; |
| 204 | + $bold_green = "\033[1m\033[32m"; |
| 205 | + $bold_yellow = "\033[1m\033[33m"; |
| 206 | + $gray = "\033[38;5;7m"; |
| 207 | + $now = new DateTime('now'); |
| 208 | + $diff = $now->diff($certificate['valid_to'])->format('%r%a'); |
| 209 | + if($diff > 0) { |
| 210 | + if($diff <= 7) { |
| 211 | + $info = $bold_yellow . $diff . ' day' . ($diff > 1 ? 's' : '') . ' valid' . $ansi_reset; |
| 212 | + } else { |
| 213 | + $info = $bold_green . $diff . ' days valid' . $ansi_reset; |
| 214 | + } |
| 215 | + } else { |
| 216 | + $diff = abs($diff); |
| 217 | + $info = $bold_red . $diff . ' day' . ($diff != 1 ? 's' : '') . ' expired' . $ansi_reset; |
| 218 | + } |
| 219 | + // $info .= $gray . $certificate['valid_to']->format('Y-m-d H:i:s') . $ansi_reset; |
| 220 | + if($certificate['is_revoked'] === null) { |
| 221 | + $info .= $gray . ' (no OCSP)' . $ansi_reset; |
| 222 | + } elseif($certificate['is_revoked']) { |
| 223 | + $info .= $bold_red . ' REVOKED' . $ansi_reset; |
| 224 | + } |
| 225 | + return $info; |
| 226 | + } |
| 227 | + |
| 228 | + private function getCertificates() { |
| 229 | + global $app; |
| 230 | + $this->swriteln('Getting all certificates…'); |
| 231 | + $certificates = $app->letsencrypt->get_certificate_list(); |
| 232 | + if(empty($certificates)) { |
| 233 | + $this->swriteln('No certificates found'); |
| 234 | + } |
| 235 | + return $certificates; |
| 236 | + } |
94 | 237 | } |
95 | 238 |
|
0 commit comments