Ejemplo n.º 1
0
 private function doExecute(Manager $args)
 {
     $keyStore = new KeyStore(\Kelunik\AcmeClient\normalizePath($args->get("storage")));
     $server = \Kelunik\AcmeClient\resolveServer($args->get("server"));
     $keyFile = \Kelunik\AcmeClient\serverToKeyname($server);
     $keyPair = (yield $keyStore->get("accounts/{$keyFile}.pem"));
     $acme = $this->acmeFactory->build($server, $keyPair);
     $this->climate->br();
     $this->climate->whisper("    Revoking certificate ...");
     $path = \Kelunik\AcmeClient\normalizePath($args->get("storage")) . "/certs/" . $keyFile . "/" . $args->get("name") . "/cert.pem";
     try {
         $pem = (yield \Amp\File\get($path));
         $cert = new Certificate($pem);
     } catch (FilesystemException $e) {
         throw new \RuntimeException("There's no such certificate (" . $path . ")");
     }
     if ($cert->getValidTo() < time()) {
         $this->climate->comment("    Certificate did already expire, no need to revoke it.");
     }
     $names = $cert->getNames();
     $this->climate->whisper("    Certificate was valid for " . count($names) . " domains.");
     $this->climate->whisper("     - " . implode(PHP_EOL . "     - ", $names) . PHP_EOL);
     (yield $acme->revokeCertificate($pem));
     $this->climate->br();
     $this->climate->info("    Certificate has been revoked.");
     (yield (new CertificateStore(\Kelunik\AcmeClient\normalizePath($args->get("storage")) . "/certs/" . $keyFile))->delete($args->get("name")));
     (yield new CoroutineResult(0));
 }
Ejemplo n.º 2
0
 private function doGet($name)
 {
     Assert::string($name, "Name must be a string. Got: %s");
     try {
         $contents = (yield \Amp\File\get($this->root . "/" . $name . "/cert.pem"));
         (yield new CoroutineResult($contents));
     } catch (FilesystemException $e) {
         throw new CertificateStoreException("Failed to load certificate.", 0, $e);
     }
 }
Ejemplo n.º 3
0
 private function doGet($path)
 {
     if (!is_string($path)) {
         throw new InvalidArgumentException(sprintf("\$root must be of type string, %s given.", gettype($path)));
     }
     $file = $this->root . "/" . $path;
     $realpath = realpath($file);
     if (!$realpath) {
         throw new KeyStoreException("File not found: '{$file}'");
     }
     $privateKey = (yield \Amp\File\get($realpath));
     $res = openssl_pkey_get_private($privateKey);
     if ($res === false) {
         throw new KeyStoreException("Invalid private key: '{$file}'");
     }
     $publicKey = openssl_pkey_get_details($res)["key"];
     (yield new CoroutineResult(new KeyPair($privateKey, $publicKey)));
 }
Ejemplo n.º 4
0
 /**
  * @param Manager $args
  * @return \Generator
  */
 private function doExecute(Manager $args)
 {
     $configPath = $args->get("config");
     try {
         $config = Yaml::parse((yield \Amp\File\get($configPath)));
     } catch (FilesystemException $e) {
         $this->climate->error("Config file ({$configPath}) not found.");
         (yield new CoroutineResult(self::EXIT_CONFIG_ERROR));
         return;
     } catch (ParseException $e) {
         $this->climate->error("Config file ({$configPath}) had an invalid format and couldn't be parsed.");
         (yield new CoroutineResult(self::EXIT_CONFIG_ERROR));
         return;
     }
     if ($args->defined("server")) {
         $config["server"] = $args->get("server");
     } else {
         if (!isset($config["server"]) && $args->exists("server")) {
             $config["server"] = $args->get("server");
         }
     }
     if ($args->defined("storage")) {
         $config["storage"] = $args->get("storage");
     } else {
         if (!isset($config["storage"]) && $args->exists("storage")) {
             $config["storage"] = $args->get("storage");
         }
     }
     if (!isset($config["server"])) {
         $this->climate->error("Config file ({$configPath}) didn't have a 'server' set nor was it passed as command line argument.");
         (yield new CoroutineResult(self::EXIT_CONFIG_ERROR));
         return;
     }
     if (!isset($config["storage"])) {
         $this->climate->error("Config file ({$configPath}) didn't have a 'storage' set nor was it passed as command line argument.");
         (yield new CoroutineResult(self::EXIT_CONFIG_ERROR));
         return;
     }
     if (!isset($config["email"])) {
         $this->climate->error("Config file ({$configPath}) didn't have a 'email' set.");
         (yield new CoroutineResult(self::EXIT_CONFIG_ERROR));
         return;
     }
     if (!isset($config["certificates"]) || !is_array($config["certificates"])) {
         $this->climate->error("Config file ({$configPath}) didn't have a 'certificates' section that's an array.");
         (yield new CoroutineResult(self::EXIT_CONFIG_ERROR));
         return;
     }
     $command = implode(" ", array_map("escapeshellarg", [PHP_BINARY, $GLOBALS["argv"][0], "setup", "--server", $config["server"], "--storage", $config["storage"], "--email", $config["email"]]));
     $process = new Process($command);
     $result = (yield $process->exec(Process::BUFFER_ALL));
     if ($result->exit !== 0) {
         $this->climate->error("Registration failed ({$result->exit})");
         $this->climate->error($command);
         $this->climate->br()->out($result->stdout);
         $this->climate->br()->error($result->stderr);
         (yield new CoroutineResult(self::EXIT_SETUP_ERROR));
         return;
     }
     $certificateChunks = array_chunk($config["certificates"], 10, true);
     $errors = [];
     $values = [];
     foreach ($certificateChunks as $certificateChunk) {
         $promises = [];
         foreach ($certificateChunk as $certificate) {
             $promises[] = \Amp\resolve($this->checkAndIssue($certificate, $config["server"], $config["storage"]));
         }
         list($chunkErrors, $chunkValues) = (yield \Amp\any($promises));
         $errors += $chunkErrors;
         $values += $chunkValues;
     }
     $status = ["no_change" => count(array_filter($values, function ($value) {
         return $value === self::STATUS_NO_CHANGE;
     })), "renewed" => count(array_filter($values, function ($value) {
         return $value === self::STATUS_RENEWED;
     })), "failure" => count($errors)];
     if ($status["renewed"] > 0) {
         foreach ($values as $i => $value) {
             if ($value === self::STATUS_RENEWED) {
                 $certificate = $config["certificates"][$i];
                 $this->climate->info("Certificate for " . implode(", ", array_keys($this->toDomainPathMap($certificate["paths"]))) . " successfully renewed.");
             }
         }
     }
     if ($status["failure"] > 0) {
         foreach ($errors as $i => $error) {
             $certificate = $config["certificates"][$i];
             $this->climate->error("Issuance for the following domains failed: " . implode(", ", array_keys($this->toDomainPathMap($certificate["paths"]))));
             $this->climate->error("Reason: {$error}");
         }
         $exitCode = $status["renewed"] > 0 ? self::EXIT_ISSUANCE_PARTIAL : self::EXIT_ISSUANCE_ERROR;
         (yield new CoroutineResult($exitCode));
         return;
     }
     if ($status["renewed"] > 0) {
         (yield new CoroutineResult(self::EXIT_ISSUANCE_OK));
         return;
     }
 }
Ejemplo n.º 5
0
function __loadHostsFile($path = null)
{
    $data = [];
    if (empty($path)) {
        $path = \stripos(PHP_OS, "win") === 0 ? 'C:\\Windows\\system32\\drivers\\etc\\hosts' : '/etc/hosts';
    }
    try {
        $contents = (yield \Amp\File\get($path));
    } catch (\Exception $e) {
        (yield new CoroutineResult($data));
        return;
    }
    $lines = \array_filter(\array_map("trim", \explode("\n", $contents)));
    foreach ($lines as $line) {
        if ($line[0] === "#") {
            continue;
        }
        $parts = \preg_split('/\\s+/', $line);
        if (!($ip = @\inet_pton($parts[0]))) {
            continue;
        } elseif (isset($ip[4])) {
            $key = Record::AAAA;
        } else {
            $key = Record::A;
        }
        for ($i = 1, $l = \count($parts); $i < $l; $i++) {
            if (__isValidHostName($parts[$i])) {
                $data[$key][strtolower($parts[$i])] = $parts[0];
            }
        }
    }
    (yield new CoroutineResult($data));
}
Ejemplo n.º 6
0
 private function loadHostsFile($path = null)
 {
     $data = [];
     if (empty($path)) {
         $path = \stripos(PHP_OS, "win") === 0 ? 'C:\\Windows\\system32\\drivers\\etc\\hosts' : '/etc/hosts';
     }
     try {
         $contents = (yield \Amp\File\get($path));
     } catch (\Exception $e) {
         (yield new CoroutineResult($data));
         return;
     }
     $lines = \array_filter(\array_map("trim", \explode("\n", $contents)));
     foreach ($lines as $line) {
         if ($line[0] === "#") {
             continue;
         }
         $parts = \preg_split('/\\s+/', $line);
         if (!($ip = @\inet_pton($parts[0]))) {
             continue;
         } elseif (isset($ip[4])) {
             $key = Record::AAAA;
         } else {
             $key = Record::A;
         }
         for ($i = 1, $l = \count($parts); $i < $l; $i++) {
             if ($this->isValidHostName($parts[$i])) {
                 $data[$key][strtolower($parts[$i])] = $parts[0];
             }
         }
     }
     // Windows does not include localhost in its host file. Fetch it from the system instead
     if (!isset($data[Record::A]["localhost"]) && !isset($data[Record::AAAA]["localhost"])) {
         // PHP currently provides no way to **resolve** IPv6 hostnames (not even with fallback)
         $local = gethostbyname("localhost");
         if ($local !== "localhost") {
             $data[Record::A]["localhost"] = $local;
         } else {
             $data[Record::AAAA]["localhost"] = "::1";
         }
     }
     (yield new CoroutineResult($data));
 }