Fixes to ssl/tls, misc improvements

* Use the PHP context options to configure tls rather than reinventing
  the wheel.
* Properly setup the SocketServer for ssl
* Added generic getter for config values
This commit is contained in:
Chris 2024-03-12 15:51:50 +01:00
parent 5aa4361cc4
commit e6c85b81e5
6 changed files with 47 additions and 8 deletions

View File

@ -56,8 +56,9 @@ if (isset($opts['C'])) {
allow_origin: '*' allow_origin: '*'
csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'" csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'"
encryption: encryption:
cert: foo.pem local_cert: ~
key: foo.key local_pk: ~
passphrase: ~
publish: publish:
overwrite_ids: false overwrite_ids: false

View File

@ -14,10 +14,11 @@ server:
# Content-Security-Policy # Content-Security-Policy
csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'" csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'"
# Setup encryption # Setup encryption context, see PHPs TLS context options
encryption: #encryption:
cert: foo.pem #local_cert: foo.pem
key: foo.key #locak_pk: foo.key
#passphrase: somepassphrase
publish: publish:
# Assign a UUID to published messages even if one is already set in the message # Assign a UUID to published messages even if one is already set in the message

View File

@ -41,6 +41,24 @@ class Configuration
return $config; return $config;
} }
/**
* Retrieve a key from the configuration. If the key ends with a dot, all values
* with keys starting with the requested key are returned. If the key is a single
* dot, all keys are matched and all values returned.
*
* @param string $key
* @param mixed $default Default value
* @return mixed
*/
public function get(string $key, $default = null): mixed
{
if ($key === '.')
return $this->config;
if (str_ends_with($key, "."))
return array_filter($this->config, fn($k)=>str_starts_with($k,$key), ARRAY_FILTER_USE_KEY);
return $this->config[$key] ?? $default;
}
public function setPublicUrl(string $publicUrl): self public function setPublicUrl(string $publicUrl): self
{ {
$this->config['server.public_url'] = $publicUrl; $this->config['server.public_url'] = $publicUrl;

View File

@ -9,6 +9,7 @@ use NoccyLabs\Mercureact\Http\Server;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use React\EventLoop\Loop; use React\EventLoop\Loop;
use React\EventLoop\LoopInterface; use React\EventLoop\LoopInterface;
use React\Socket\SecureServer;
use React\Socket\SocketServer; use React\Socket\SocketServer;
class Daemon class Daemon
@ -48,7 +49,21 @@ class Daemon
$this->logger->warning("Empty listening address. You won't make it far."); $this->logger->warning("Empty listening address. You won't make it far.");
return; return;
} }
$socket = new SocketServer("tcp://".$listenAddress);
$certificate = $this->config->get("server.encryption.local_cert");
if ($certificate) {
$this->logger->info("Using local cert: {$certificate}");
$context = [
'tls' => $this->config->get("server.encryption.")
];
$uri = 'tls://' . $listenAddress;
} else {
$uri = 'tcp://' . $listenAddress;
}
$socket = new SocketServer($uri, $context??[]);
$this->server->listen($socket); $this->server->listen($socket);
} }

View File

@ -80,7 +80,7 @@ class Server
$this->server->listen($socket); $this->server->listen($socket);
$this->logger->info(sprintf( $this->logger->info(sprintf(
"Listening on %s", "Listening on %s",
str_replace("tcp://",($socket instanceof SecureServer?"https://":"http://"),$socket->getAddress()) strtr($socket->getAddress(), [ "tcp://"=>"http://", "tls://"=>"https://"])
)); ));
} }

View File

@ -15,12 +15,14 @@ class TopicTest extends \PHPUnit\Framework\TestCase
public function isAuthorized():bool { return true; } public function isAuthorized():bool { return true; }
public function deliver(Message $message):void { $this->messages[] = $message; } public function deliver(Message $message):void { $this->messages[] = $message; }
public function getPayload(): ?array { return null; } public function getPayload(): ?array { return null; }
public function getId(): string { return ""; }
}; };
$unauthorizedSubscriber = new class implements SubscriberInterface { $unauthorizedSubscriber = new class implements SubscriberInterface {
public array $messages = []; public array $messages = [];
public function isAuthorized():bool { return false; } public function isAuthorized():bool { return false; }
public function deliver(Message $message):void { $this->messages[] = $message; } public function deliver(Message $message):void { $this->messages[] = $message; }
public function getPayload(): ?array { return null; } public function getPayload(): ?array { return null; }
public function getId(): string { return ""; }
}; };
$topic = new Topic("foo"); $topic = new Topic("foo");
@ -41,12 +43,14 @@ class TopicTest extends \PHPUnit\Framework\TestCase
public function isAuthorized():bool { return true; } public function isAuthorized():bool { return true; }
public function deliver(Message $message):void { $this->messages[] = $message; } public function deliver(Message $message):void { $this->messages[] = $message; }
public function getPayload(): ?array { return null; } public function getPayload(): ?array { return null; }
public function getId(): string { return ""; }
}; };
$unauthorizedSubscriber = new class implements SubscriberInterface { $unauthorizedSubscriber = new class implements SubscriberInterface {
public array $messages = []; public array $messages = [];
public function isAuthorized():bool { return false; } public function isAuthorized():bool { return false; }
public function deliver(Message $message):void { $this->messages[] = $message; } public function deliver(Message $message):void { $this->messages[] = $message; }
public function getPayload(): ?array { return null; } public function getPayload(): ?array { return null; }
public function getId(): string { return ""; }
}; };
$topic = new Topic("foo"); $topic = new Topic("foo");