From: Maxence Lange Date: Fri, 22 Nov 2024 17:20:06 +0000 (-0100) Subject: feat(signatory): switch to qbmapper X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=618ff23cf6d74a41dc71239ace3b86e56794287a;p=nextcloud-server.git feat(signatory): switch to qbmapper Signed-off-by: Maxence Lange --- diff --git a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php index e277b9b6389..a243d286c71 100644 --- a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php +++ b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php @@ -10,8 +10,8 @@ use NCU\Security\Signature\Exceptions\IncomingRequestException; use NCU\Security\Signature\Exceptions\SignatoryNotFoundException; use NCU\Security\Signature\Exceptions\SignatureException; use NCU\Security\Signature\Exceptions\SignatureNotFoundException; +use NCU\Security\Signature\IIncomingSignedRequest; use NCU\Security\Signature\ISignatureManager; -use NCU\Security\Signature\Model\IIncomingSignedRequest; use OC\OCM\OCMSignatoryManager; use OCA\CloudFederationAPI\Config; use OCA\CloudFederationAPI\ResponseDefinitions; @@ -373,7 +373,7 @@ class RequestHandlerController extends Controller { if ($signedRequest === null) { $instance = $this->getHostFromFederationId($value); try { - $this->signatureManager->searchSignatory($instance); + $this->signatureManager->getSignatory($instance); throw new IncomingRequestException('instance is supposed to sign its request'); } catch (SignatoryNotFoundException) { return; @@ -434,7 +434,7 @@ class RequestHandlerController extends Controller { $instance = $this->getHostFromFederationId($entry); if ($signedRequest === null) { try { - $this->signatureManager->searchSignatory($instance); + $this->signatureManager->getSignatory($instance); throw new IncomingRequestException('instance is supposed to sign its request'); } catch (SignatoryNotFoundException) { return; diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 87e617ed4e6..b3d4c92220c 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -12,6 +12,9 @@ return array( 'NCU\\Config\\Exceptions\\UnknownKeyException' => $baseDir . '/lib/unstable/Config/Exceptions/UnknownKeyException.php', 'NCU\\Config\\IUserConfig' => $baseDir . '/lib/unstable/Config/IUserConfig.php', 'NCU\\Config\\ValueType' => $baseDir . '/lib/unstable/Config/ValueType.php', + 'NCU\\Security\\Signature\\Enum\\SignatoryStatus' => $baseDir . '/lib/unstable/Security/Signature/Enum/SignatoryStatus.php', + 'NCU\\Security\\Signature\\Enum\\SignatoryType' => $baseDir . '/lib/unstable/Security/Signature/Enum/SignatoryType.php', + 'NCU\\Security\\Signature\\Enum\\SignatureAlgorithm' => $baseDir . '/lib/unstable/Security/Signature/Enum/SignatureAlgorithm.php', 'NCU\\Security\\Signature\\Exceptions\\IdentityNotFoundException' => $baseDir . '/lib/unstable/Security/Signature/Exceptions/IdentityNotFoundException.php', 'NCU\\Security\\Signature\\Exceptions\\IncomingRequestException' => $baseDir . '/lib/unstable/Security/Signature/Exceptions/IncomingRequestException.php', 'NCU\\Security\\Signature\\Exceptions\\InvalidKeyOriginException' => $baseDir . '/lib/unstable/Security/Signature/Exceptions/InvalidKeyOriginException.php', @@ -22,15 +25,12 @@ return array( 'NCU\\Security\\Signature\\Exceptions\\SignatureElementNotFoundException' => $baseDir . '/lib/unstable/Security/Signature/Exceptions/SignatureElementNotFoundException.php', 'NCU\\Security\\Signature\\Exceptions\\SignatureException' => $baseDir . '/lib/unstable/Security/Signature/Exceptions/SignatureException.php', 'NCU\\Security\\Signature\\Exceptions\\SignatureNotFoundException' => $baseDir . '/lib/unstable/Security/Signature/Exceptions/SignatureNotFoundException.php', + 'NCU\\Security\\Signature\\IIncomingSignedRequest' => $baseDir . '/lib/unstable/Security/Signature/IIncomingSignedRequest.php', + 'NCU\\Security\\Signature\\IOutgoingSignedRequest' => $baseDir . '/lib/unstable/Security/Signature/IOutgoingSignedRequest.php', 'NCU\\Security\\Signature\\ISignatoryManager' => $baseDir . '/lib/unstable/Security/Signature/ISignatoryManager.php', 'NCU\\Security\\Signature\\ISignatureManager' => $baseDir . '/lib/unstable/Security/Signature/ISignatureManager.php', - 'NCU\\Security\\Signature\\Model\\IIncomingSignedRequest' => $baseDir . '/lib/unstable/Security/Signature/Model/IIncomingSignedRequest.php', - 'NCU\\Security\\Signature\\Model\\IOutgoingSignedRequest' => $baseDir . '/lib/unstable/Security/Signature/Model/IOutgoingSignedRequest.php', - 'NCU\\Security\\Signature\\Model\\ISignatory' => $baseDir . '/lib/unstable/Security/Signature/Model/ISignatory.php', - 'NCU\\Security\\Signature\\Model\\ISignedRequest' => $baseDir . '/lib/unstable/Security/Signature/Model/ISignedRequest.php', - 'NCU\\Security\\Signature\\Model\\SignatoryStatus' => $baseDir . '/lib/unstable/Security/Signature/Model/SignatoryStatus.php', - 'NCU\\Security\\Signature\\Model\\SignatoryType' => $baseDir . '/lib/unstable/Security/Signature/Model/SignatoryType.php', - 'NCU\\Security\\Signature\\SignatureAlgorithm' => $baseDir . '/lib/unstable/Security/Signature/SignatureAlgorithm.php', + 'NCU\\Security\\Signature\\ISignedRequest' => $baseDir . '/lib/unstable/Security/Signature/ISignedRequest.php', + 'NCU\\Security\\Signature\\Model\\Signatory' => $baseDir . '/lib/unstable/Security/Signature/Model/Signatory.php', 'OCP\\Accounts\\IAccount' => $baseDir . '/lib/public/Accounts/IAccount.php', 'OCP\\Accounts\\IAccountManager' => $baseDir . '/lib/public/Accounts/IAccountManager.php', 'OCP\\Accounts\\IAccountProperty' => $baseDir . '/lib/public/Accounts/IAccountProperty.php', @@ -1929,9 +1929,9 @@ return array( 'OC\\Security\\RateLimiting\\Limiter' => $baseDir . '/lib/private/Security/RateLimiting/Limiter.php', 'OC\\Security\\RemoteHostValidator' => $baseDir . '/lib/private/Security/RemoteHostValidator.php', 'OC\\Security\\SecureRandom' => $baseDir . '/lib/private/Security/SecureRandom.php', + 'OC\\Security\\Signature\\Db\\SignatoryMapper' => $baseDir . '/lib/private/Security/Signature/Db/SignatoryMapper.php', 'OC\\Security\\Signature\\Model\\IncomingSignedRequest' => $baseDir . '/lib/private/Security/Signature/Model/IncomingSignedRequest.php', 'OC\\Security\\Signature\\Model\\OutgoingSignedRequest' => $baseDir . '/lib/private/Security/Signature/Model/OutgoingSignedRequest.php', - 'OC\\Security\\Signature\\Model\\Signatory' => $baseDir . '/lib/private/Security/Signature/Model/Signatory.php', 'OC\\Security\\Signature\\Model\\SignedRequest' => $baseDir . '/lib/private/Security/Signature/Model/SignedRequest.php', 'OC\\Security\\Signature\\SignatureManager' => $baseDir . '/lib/private/Security/Signature/SignatureManager.php', 'OC\\Security\\TrustedDomainHelper' => $baseDir . '/lib/private/Security/TrustedDomainHelper.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 640924c6579..31e93679086 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -53,6 +53,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'NCU\\Config\\Exceptions\\UnknownKeyException' => __DIR__ . '/../../..' . '/lib/unstable/Config/Exceptions/UnknownKeyException.php', 'NCU\\Config\\IUserConfig' => __DIR__ . '/../../..' . '/lib/unstable/Config/IUserConfig.php', 'NCU\\Config\\ValueType' => __DIR__ . '/../../..' . '/lib/unstable/Config/ValueType.php', + 'NCU\\Security\\Signature\\Enum\\SignatoryStatus' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Enum/SignatoryStatus.php', + 'NCU\\Security\\Signature\\Enum\\SignatoryType' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Enum/SignatoryType.php', + 'NCU\\Security\\Signature\\Enum\\SignatureAlgorithm' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Enum/SignatureAlgorithm.php', 'NCU\\Security\\Signature\\Exceptions\\IdentityNotFoundException' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Exceptions/IdentityNotFoundException.php', 'NCU\\Security\\Signature\\Exceptions\\IncomingRequestException' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Exceptions/IncomingRequestException.php', 'NCU\\Security\\Signature\\Exceptions\\InvalidKeyOriginException' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Exceptions/InvalidKeyOriginException.php', @@ -63,15 +66,12 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'NCU\\Security\\Signature\\Exceptions\\SignatureElementNotFoundException' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Exceptions/SignatureElementNotFoundException.php', 'NCU\\Security\\Signature\\Exceptions\\SignatureException' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Exceptions/SignatureException.php', 'NCU\\Security\\Signature\\Exceptions\\SignatureNotFoundException' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Exceptions/SignatureNotFoundException.php', + 'NCU\\Security\\Signature\\IIncomingSignedRequest' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/IIncomingSignedRequest.php', + 'NCU\\Security\\Signature\\IOutgoingSignedRequest' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/IOutgoingSignedRequest.php', 'NCU\\Security\\Signature\\ISignatoryManager' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/ISignatoryManager.php', 'NCU\\Security\\Signature\\ISignatureManager' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/ISignatureManager.php', - 'NCU\\Security\\Signature\\Model\\IIncomingSignedRequest' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Model/IIncomingSignedRequest.php', - 'NCU\\Security\\Signature\\Model\\IOutgoingSignedRequest' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Model/IOutgoingSignedRequest.php', - 'NCU\\Security\\Signature\\Model\\ISignatory' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Model/ISignatory.php', - 'NCU\\Security\\Signature\\Model\\ISignedRequest' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Model/ISignedRequest.php', - 'NCU\\Security\\Signature\\Model\\SignatoryStatus' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Model/SignatoryStatus.php', - 'NCU\\Security\\Signature\\Model\\SignatoryType' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Model/SignatoryType.php', - 'NCU\\Security\\Signature\\SignatureAlgorithm' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/SignatureAlgorithm.php', + 'NCU\\Security\\Signature\\ISignedRequest' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/ISignedRequest.php', + 'NCU\\Security\\Signature\\Model\\Signatory' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Model/Signatory.php', 'OCP\\Accounts\\IAccount' => __DIR__ . '/../../..' . '/lib/public/Accounts/IAccount.php', 'OCP\\Accounts\\IAccountManager' => __DIR__ . '/../../..' . '/lib/public/Accounts/IAccountManager.php', 'OCP\\Accounts\\IAccountProperty' => __DIR__ . '/../../..' . '/lib/public/Accounts/IAccountProperty.php', @@ -1970,9 +1970,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Security\\RateLimiting\\Limiter' => __DIR__ . '/../../..' . '/lib/private/Security/RateLimiting/Limiter.php', 'OC\\Security\\RemoteHostValidator' => __DIR__ . '/../../..' . '/lib/private/Security/RemoteHostValidator.php', 'OC\\Security\\SecureRandom' => __DIR__ . '/../../..' . '/lib/private/Security/SecureRandom.php', + 'OC\\Security\\Signature\\Db\\SignatoryMapper' => __DIR__ . '/../../..' . '/lib/private/Security/Signature/Db/SignatoryMapper.php', 'OC\\Security\\Signature\\Model\\IncomingSignedRequest' => __DIR__ . '/../../..' . '/lib/private/Security/Signature/Model/IncomingSignedRequest.php', 'OC\\Security\\Signature\\Model\\OutgoingSignedRequest' => __DIR__ . '/../../..' . '/lib/private/Security/Signature/Model/OutgoingSignedRequest.php', - 'OC\\Security\\Signature\\Model\\Signatory' => __DIR__ . '/../../..' . '/lib/private/Security/Signature/Model/Signatory.php', 'OC\\Security\\Signature\\Model\\SignedRequest' => __DIR__ . '/../../..' . '/lib/private/Security/Signature/Model/SignedRequest.php', 'OC\\Security\\Signature\\SignatureManager' => __DIR__ . '/../../..' . '/lib/private/Security/Signature/SignatureManager.php', 'OC\\Security\\TrustedDomainHelper' => __DIR__ . '/../../..' . '/lib/private/Security/TrustedDomainHelper.php', diff --git a/lib/private/OCM/Model/OCMProvider.php b/lib/private/OCM/Model/OCMProvider.php index 95ba83882f2..32068efe3eb 100644 --- a/lib/private/OCM/Model/OCMProvider.php +++ b/lib/private/OCM/Model/OCMProvider.php @@ -9,8 +9,7 @@ declare(strict_types=1); namespace OC\OCM\Model; -use NCU\Security\Signature\Model\ISignatory; -use OC\Security\Signature\Model\Signatory; +use NCU\Security\Signature\Model\Signatory; use OCP\EventDispatcher\IEventDispatcher; use OCP\OCM\Events\ResourceTypeRegisterEvent; use OCP\OCM\Exceptions\OCMArgumentException; @@ -27,7 +26,7 @@ class OCMProvider implements IOCMProvider { private string $endPoint = ''; /** @var IOCMResource[] */ private array $resourceTypes = []; - private ?ISignatory $signatory = null; + private ?Signatory $signatory = null; private bool $emittedEvent = false; public function __construct( @@ -154,11 +153,11 @@ class OCMProvider implements IOCMProvider { throw new OCMArgumentException('resource not found'); } - public function setSignatory(ISignatory $signatory): void { + public function setSignatory(Signatory $signatory): void { $this->signatory = $signatory; } - public function getSignatory(): ?ISignatory { + public function getSignatory(): ?Signatory { return $this->signatory; } @@ -209,7 +208,7 @@ class OCMProvider implements IOCMProvider { * enabled: bool, * apiVersion: '1.0-proposal1', * endPoint: string, - * publicKey: ISignatory|null, + * publicKey: Signatory|null, * resourceTypes: list, diff --git a/lib/private/OCM/OCMSignatoryManager.php b/lib/private/OCM/OCMSignatoryManager.php index c7eb9ccda5a..ca0a295468f 100644 --- a/lib/private/OCM/OCMSignatoryManager.php +++ b/lib/private/OCM/OCMSignatoryManager.php @@ -9,13 +9,12 @@ declare(strict_types=1); namespace OC\OCM; +use NCU\Security\Signature\Enum\SignatoryType; use NCU\Security\Signature\Exceptions\IdentityNotFoundException; use NCU\Security\Signature\ISignatoryManager; use NCU\Security\Signature\ISignatureManager; -use NCU\Security\Signature\Model\ISignatory; -use NCU\Security\Signature\Model\SignatoryType; +use NCU\Security\Signature\Model\Signatory; use OC\Security\IdentityProof\Manager; -use OC\Security\Signature\Model\Signatory; use OCP\IAppConfig; use OCP\IURLGenerator; use OCP\OCM\Exceptions\OCMProviderException; @@ -68,11 +67,11 @@ class OCMSignatoryManager implements ISignatoryManager { /** * @inheritDoc * - * @return ISignatory + * @return Signatory * @throws IdentityNotFoundException * @since 31.0.0 */ - public function getLocalSignatory(): ISignatory { + public function getLocalSignatory(): Signatory { /** * TODO: manage multiple identity (external, internal, ...) to allow a limitation * based on the requested interface (ie. only accept shares from globalscale) @@ -125,10 +124,10 @@ class OCMSignatoryManager implements ISignatoryManager { * * @param string $remote * - * @return ISignatory|null must be NULL if no signatory is found + * @return Signatory|null must be NULL if no signatory is found * @since 31.0.0 */ - public function getRemoteSignatory(string $remote): ?ISignatory { + public function getRemoteSignatory(string $remote): ?Signatory { try { return $this->getRemoteSignatoryFromHost($remote); } catch (OCMProviderException $e) { @@ -142,11 +141,11 @@ class OCMSignatoryManager implements ISignatoryManager { * * @param string $host * - * @return ISignatory|null + * @return Signatory|null * @throws OCMProviderException on fail to discover ocm services * @since 31.0.0 */ - public function getRemoteSignatoryFromHost(string $host): ?ISignatory { + public function getRemoteSignatoryFromHost(string $host): ?Signatory { $ocmProvider = $this->ocmDiscoveryService->discover($host, true); $signatory = $ocmProvider->getSignatory(); diff --git a/lib/private/Security/IdentityProof/Manager.php b/lib/private/Security/IdentityProof/Manager.php index de0b3fe6bd1..935c18bb81d 100644 --- a/lib/private/Security/IdentityProof/Manager.php +++ b/lib/private/Security/IdentityProof/Manager.php @@ -133,8 +133,8 @@ class Manager { public function hasAppKey(string $app, string $name): bool { $id = $this->generateAppKeyId($app, $name); try { - $this->appData->getFolder($id); - return true; + $folder = $this->appData->getFolder($id); + return ($folder->fileExists('public') && $folder->fileExists('private')); } catch (NotFoundException) { return false; } @@ -151,11 +151,11 @@ class Manager { public function deleteAppKey(string $app, string $name): bool { try { $folder = $this->appData->getFolder($this->generateAppKeyId($app, $name)); + $folder->delete(); + return true; } catch (NotFoundException) { return false; } - $folder->delete(); - return true; } private function generateAppKeyId(string $app, string $name): string { diff --git a/lib/private/Security/Signature/Db/SignatoryMapper.php b/lib/private/Security/Signature/Db/SignatoryMapper.php new file mode 100644 index 00000000000..47b79320548 --- /dev/null +++ b/lib/private/Security/Signature/Db/SignatoryMapper.php @@ -0,0 +1,114 @@ + + */ +class SignatoryMapper extends QBMapper { + public const TABLE = 'sec_signatory'; + + public function __construct( + IDBConnection $db, + ) { + parent::__construct($db, self::TABLE, Signatory::class); + } + + /** + * + */ + public function getByHost(string $host, string $account = ''): Signatory { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('host', $qb->createNamedParameter($host))) + ->andWhere($qb->expr()->eq('account', $qb->createNamedParameter($account))); + + try { + return $this->findEntity($qb); + } catch (DoesNotExistException) { + throw new SignatoryNotFoundException('no signatory found'); + } + } + + /** + */ + public function getByKeyId(string $keyId): Signatory { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('key_id_sum', $qb->createNamedParameter($this->hashKeyId($keyId)))); + + try { + return $this->findEntity($qb); + } catch (DoesNotExistException) { + throw new SignatoryNotFoundException('no signatory found'); + } + } + + /** + * @param string $keyId + * + * @return int + * @throws Exception + */ + public function deleteByKeyId(string $keyId): int { + $qb = $this->db->getQueryBuilder(); + $qb->delete($this->getTableName()) + ->where($qb->expr()->eq('key_id_sum', $qb->createNamedParameter($this->hashKeyId($keyId)))); + + return $qb->executeStatement(); + } + + /** + * @param Signatory $signatory + * + * @return int + */ + public function updateMetadata(Signatory $signatory): int { + $qb = $this->db->getQueryBuilder(); + $qb->update($this->getTableName()) + ->set('metadata', $qb->createNamedParameter(json_encode($signatory->getMetadata()))) + ->set('last_updated', $qb->createNamedParameter(time())); + $qb->where($qb->expr()->eq('key_id_sum', $qb->createNamedParameter($this->hashKeyId($signatory->getKeyId())))); + + return $qb->executeStatement(); + } + + /** + * @param Signatory $signator + */ + public function updatePublicKey(Signatory $signatory): int { + $qb = $this->db->getQueryBuilder(); + $qb->update($this->getTableName()) + ->set('signatory', $qb->createNamedParameter($signatory->getPublicKey())) + ->set('last_updated', $qb->createNamedParameter(time())); + $qb->where($qb->expr()->eq('key_id_sum', $qb->createNamedParameter($this->hashKeyId($signatory->getKeyId())))); + + return $qb->executeStatement(); + } + + /** + * returns a hash version for keyId for better index in the database + * + * @param string $keyId + * + * @return string + */ + private function hashKeyId(string $keyId): string { + return hash('sha256', $keyId); + } +} diff --git a/lib/private/Security/Signature/Model/IncomingSignedRequest.php b/lib/private/Security/Signature/Model/IncomingSignedRequest.php index 77914d1e3b2..a2bf9fd0bcc 100644 --- a/lib/private/Security/Signature/Model/IncomingSignedRequest.php +++ b/lib/private/Security/Signature/Model/IncomingSignedRequest.php @@ -14,9 +14,9 @@ use NCU\Security\Signature\Exceptions\IncomingRequestException; use NCU\Security\Signature\Exceptions\SignatoryException; use NCU\Security\Signature\Exceptions\SignatureElementNotFoundException; use NCU\Security\Signature\Exceptions\SignatureNotFoundException; +use NCU\Security\Signature\IIncomingSignedRequest; use NCU\Security\Signature\ISignatureManager; -use NCU\Security\Signature\Model\IIncomingSignedRequest; -use NCU\Security\Signature\Model\ISignatory; +use NCU\Security\Signature\Model\Signatory; use OC\Security\Signature\SignatureManager; use OCP\IRequest; @@ -141,7 +141,7 @@ class IncomingSignedRequest extends SignedRequest implements /** * @inheritDoc * - * @param ISignatory $signatory + * @param Signatory $signatory * * @return $this * @throws IdentityNotFoundException @@ -149,7 +149,7 @@ class IncomingSignedRequest extends SignedRequest implements * @throws SignatoryException * @since 31.0.0 */ - public function setSignatory(ISignatory $signatory): self { + public function setSignatory(Signatory $signatory): self { $identity = \OCP\Server::get(ISignatureManager::class)->extractIdentityFromUri($signatory->getKeyId()); if ($identity !== $this->getOrigin()) { throw new SignatoryException('keyId from provider is different from the one from signed request'); diff --git a/lib/private/Security/Signature/Model/OutgoingSignedRequest.php b/lib/private/Security/Signature/Model/OutgoingSignedRequest.php index d2d5b95e7b6..611a968d1d2 100644 --- a/lib/private/Security/Signature/Model/OutgoingSignedRequest.php +++ b/lib/private/Security/Signature/Model/OutgoingSignedRequest.php @@ -9,10 +9,10 @@ declare(strict_types=1); namespace OC\Security\Signature\Model; use JsonSerializable; +use NCU\Security\Signature\Enum\SignatureAlgorithm; +use NCU\Security\Signature\IOutgoingSignedRequest; use NCU\Security\Signature\ISignatoryManager; use NCU\Security\Signature\ISignatureManager; -use NCU\Security\Signature\Model\IOutgoingSignedRequest; -use NCU\Security\Signature\SignatureAlgorithm; use OC\Security\Signature\SignatureManager; /** @@ -53,7 +53,6 @@ class OutgoingSignedRequest extends SignedRequest implements $signing = $headerList = []; foreach ($headers as $element => $value) { - $value = $headers[$element]; $signing[] = $element . ': ' . $value; $headerList[] = $element; if ($element !== '(request-target)') { diff --git a/lib/private/Security/Signature/Model/Signatory.php b/lib/private/Security/Signature/Model/Signatory.php deleted file mode 100644 index b28d2c0415f..00000000000 --- a/lib/private/Security/Signature/Model/Signatory.php +++ /dev/null @@ -1,147 +0,0 @@ -keyId = $keyId; - } - } - - public function setProviderId(string $providerId): self { - $this->providerId = $providerId; - return $this; - } - - public function getProviderId(): string { - return $this->providerId; - } - - public function setAccount(string $account): self { - $this->account = $account; - return $this; - } - - public function getAccount(): string { - return $this->account; - } - - public function getKeyId(): string { - return $this->keyId; - } - - public function getPublicKey(): string { - return $this->publicKey; - } - - public function getPrivateKey(): string { - return $this->privateKey; - } - - public function setMetadata(array $metadata): self { - $this->metadata = $metadata; - return $this; - } - - public function getMetadata(): array { - return $this->metadata; - } - - public function setMetaValue(string $key, string|int $value): self { - $this->metadata[$key] = $value; - return $this; - } - - public function setType(SignatoryType $type): self { - $this->type = $type; - return $this; - } - public function getType(): SignatoryType { - return $this->type; - } - - public function setStatus(SignatoryStatus $status): self { - $this->status = $status; - return $this; - } - - public function getStatus(): SignatoryStatus { - return $this->status; - } - - public function setCreation(int $creation): self { - $this->creation = $creation; - return $this; - } - - public function getCreation(): int { - return $this->creation; - } - - public function setLastUpdated(int $lastUpdated): self { - $this->lastUpdated = $lastUpdated; - return $this; - } - - public function getLastUpdated(): int { - return $this->lastUpdated; - } - - public function importFromDatabase(array $row): self { - $this->setProviderId($row['provider_id'] ?? '') - ->setAccount($row['account'] ?? '') - ->setMetadata(json_decode($row['metadata'], true) ?? []) - ->setType(SignatoryType::from($row['type'] ?? 9)) - ->setStatus(SignatoryStatus::from($row['status'] ?? 1)) - ->setCreation($row['creation'] ?? 0) - ->setLastUpdated($row['last_updated'] ?? 0); - return $this; - } - - public function jsonSerialize(): array { - return [ - 'keyId' => $this->getKeyId(), - 'publicKeyPem' => $this->getPublicKey() - ]; - } -} diff --git a/lib/private/Security/Signature/Model/SignedRequest.php b/lib/private/Security/Signature/Model/SignedRequest.php index 56853ebade3..e974942a925 100644 --- a/lib/private/Security/Signature/Model/SignedRequest.php +++ b/lib/private/Security/Signature/Model/SignedRequest.php @@ -11,8 +11,8 @@ namespace OC\Security\Signature\Model; use JsonSerializable; use NCU\Security\Signature\Exceptions\SignatoryNotFoundException; use NCU\Security\Signature\Exceptions\SignatureElementNotFoundException; -use NCU\Security\Signature\Model\ISignatory; -use NCU\Security\Signature\Model\ISignedRequest; +use NCU\Security\Signature\ISignedRequest; +use NCU\Security\Signature\Model\Signatory; /** * @inheritDoc @@ -24,7 +24,7 @@ class SignedRequest implements ISignedRequest, JsonSerializable { private array $signatureElements = []; private string $clearSignature = ''; private string $signedSignature = ''; - private ?ISignatory $signatory = null; + private ?Signatory $signatory = null; public function __construct( private readonly string $body, @@ -140,11 +140,11 @@ class SignedRequest implements ISignedRequest, JsonSerializable { /** * @inheritDoc * - * @param ISignatory $signatory + * @param Signatory $signatory * @return ISignedRequest * @since 31.0.0 */ - public function setSignatory(ISignatory $signatory): ISignedRequest { + public function setSignatory(Signatory $signatory): ISignedRequest { $this->signatory = $signatory; return $this; } @@ -152,11 +152,11 @@ class SignedRequest implements ISignedRequest, JsonSerializable { /** * @inheritDoc * - * @return ISignatory + * @return Signatory * @throws SignatoryNotFoundException * @since 31.0.0 */ - public function getSignatory(): ISignatory { + public function getSignatory(): Signatory { if ($this->signatory === null) { throw new SignatoryNotFoundException(); } diff --git a/lib/private/Security/Signature/SignatureManager.php b/lib/private/Security/Signature/SignatureManager.php index 2d895b465ab..e4f4a2ed1a6 100644 --- a/lib/private/Security/Signature/SignatureManager.php +++ b/lib/private/Security/Signature/SignatureManager.php @@ -8,6 +8,8 @@ declare(strict_types=1); namespace OC\Security\Signature; +use NCU\Security\Signature\Enum\SignatoryType; +use NCU\Security\Signature\Enum\SignatureAlgorithm; use NCU\Security\Signature\Exceptions\IdentityNotFoundException; use NCU\Security\Signature\Exceptions\IncomingRequestException; use NCU\Security\Signature\Exceptions\InvalidKeyOriginException; @@ -18,19 +20,16 @@ use NCU\Security\Signature\Exceptions\SignatoryNotFoundException; use NCU\Security\Signature\Exceptions\SignatureElementNotFoundException; use NCU\Security\Signature\Exceptions\SignatureException; use NCU\Security\Signature\Exceptions\SignatureNotFoundException; +use NCU\Security\Signature\IIncomingSignedRequest; +use NCU\Security\Signature\IOutgoingSignedRequest; use NCU\Security\Signature\ISignatoryManager; use NCU\Security\Signature\ISignatureManager; -use NCU\Security\Signature\Model\IIncomingSignedRequest; -use NCU\Security\Signature\Model\IOutgoingSignedRequest; -use NCU\Security\Signature\Model\ISignatory; -use NCU\Security\Signature\Model\SignatoryType; -use NCU\Security\Signature\SignatureAlgorithm; +use NCU\Security\Signature\Model\Signatory; +use OC\Security\Signature\Db\SignatoryMapper; use OC\Security\Signature\Model\IncomingSignedRequest; use OC\Security\Signature\Model\OutgoingSignedRequest; -use OC\Security\Signature\Model\Signatory; use OCP\DB\Exception as DBException; use OCP\IAppConfig; -use OCP\IDBConnection; use OCP\IRequest; use Psr\Log\LoggerInterface; @@ -69,13 +68,12 @@ class SignatureManager implements ISignatureManager { public const DATE_HEADER = 'D, d M Y H:i:s T'; public const DATE_TTL = 300; public const SIGNATORY_TTL = 86400 * 3; - public const TABLE_SIGNATORIES = 'sec_signatory'; public const BODY_MAXSIZE = 50000; // max size of the payload of the request public const APPCONFIG_IDENTITY = 'security.signature.identity'; public function __construct( private readonly IRequest $request, - private readonly IDBConnection $connection, + private readonly SignatoryMapper $mapper, private readonly IAppConfig $appConfig, private readonly LoggerInterface $logger, ) { @@ -307,31 +305,12 @@ class SignatureManager implements ISignatureManager { * @param string $account linked account, should be used when multiple signature can exist for the same * host * - * @return ISignatory + * @return Signatory * @throws SignatoryNotFoundException if entry does not exist in local database * @since 31.0.0 */ - public function searchSignatory(string $host, string $account = ''): ISignatory { - $qb = $this->connection->getQueryBuilder(); - $qb->select( - 'id', 'provider_id', 'host', 'account', 'key_id', 'key_id_sum', 'public_key', 'metadata', 'type', - 'status', 'creation', 'last_updated' - ); - $qb->from(self::TABLE_SIGNATORIES); - $qb->where($qb->expr()->eq('host', $qb->createNamedParameter($host))); - $qb->andWhere($qb->expr()->eq('account', $qb->createNamedParameter($account))); - - $result = $qb->executeQuery(); - $row = $result->fetch(); - $result->closeCursor(); - - if (!$row) { - throw new SignatoryNotFoundException('no signatory found'); - } - - $signature = new Signatory($row['key_id'], $row['public_key']); - - return $signature->importFromDatabase($row); + public function getSignatory(string $host, string $account = ''): Signatory { + return $this->mapper->getByHost($host, $account); } @@ -386,7 +365,7 @@ class SignatureManager implements ISignatureManager { * @param ISignatoryManager $signatoryManager * @param IIncomingSignedRequest $signedRequest * - * @return ISignatory + * @return Signatory * @throws InvalidKeyOriginException * @throws SignatoryNotFoundException * @see ISignatoryManager::getRemoteSignatory @@ -394,7 +373,7 @@ class SignatureManager implements ISignatureManager { private function getSaneRemoteSignatory( ISignatoryManager $signatoryManager, IIncomingSignedRequest $signedRequest, - ): ISignatory { + ): Signatory { $signatory = $signatoryManager->getRemoteSignatory($signedRequest->getOrigin()); if ($signatory === null) { throw new SignatoryNotFoundException('empty result from getRemoteSignatory'); @@ -406,14 +385,14 @@ class SignatureManager implements ISignatureManager { } catch (SignatureElementNotFoundException) { throw new InvalidKeyOriginException('missing keyId'); } + $signatory->setProviderId($signatoryManager->getProviderId()); - return $signatory->setProviderId($signatoryManager->getProviderId()); + return $signatory; } /** * @param IIncomingSignedRequest $signedRequest * - * @return void * @throws SignatureException * @throws SignatoryNotFoundException */ @@ -477,36 +456,17 @@ class SignatureManager implements ISignatureManager { /** * @param string $keyId * - * @return ISignatory + * @return Signatory * @throws SignatoryNotFoundException */ - private function getStoredSignatory(string $keyId): ISignatory { - $qb = $this->connection->getQueryBuilder(); - $qb->select( - 'id', 'provider_id', 'host', 'account', 'key_id', 'key_id_sum', 'public_key', 'metadata', 'type', - 'status', 'creation', 'last_updated' - ); - $qb->from(self::TABLE_SIGNATORIES); - $qb->where($qb->expr()->eq('key_id_sum', $qb->createNamedParameter($this->hashKeyId($keyId)))); - - $result = $qb->executeQuery(); - $row = $result->fetch(); - $result->closeCursor(); - - if (!$row) { - throw new SignatoryNotFoundException('no signatory found in local'); - } - - $signature = new Signatory($row['key_id'], $row['public_key']); - $signature->importFromDatabase($row); - - return $signature; + private function getStoredSignatory(string $keyId): Signatory { + return $this->mapper->getByKeyId($keyId); } /** - * @param ISignatory $signatory + * @param Signatory $signatory */ - private function storeSignatory(ISignatory $signatory): void { + private function storeSignatory(Signatory $signatory): void { try { $this->insertSignatory($signatory); } catch (DBException $e) { @@ -524,34 +484,20 @@ class SignatureManager implements ISignatureManager { } /** - * @param ISignatory $signatory + * @param Signatory $signatory * @throws DBException */ - private function insertSignatory(ISignatory $signatory): void { - $qb = $this->connection->getQueryBuilder(); - $qb->insert(self::TABLE_SIGNATORIES) - ->setValue('provider_id', $qb->createNamedParameter($signatory->getProviderId())) - ->setValue('host', $qb->createNamedParameter($this->extractIdentityFromUri($signatory->getKeyId()))) - ->setValue('account', $qb->createNamedParameter($signatory->getAccount())) - ->setValue('key_id', $qb->createNamedParameter($signatory->getKeyId())) - ->setValue('key_id_sum', $qb->createNamedParameter($this->hashKeyId($signatory->getKeyId()))) - ->setValue('public_key', $qb->createNamedParameter($signatory->getPublicKey())) - ->setValue('metadata', $qb->createNamedParameter(json_encode($signatory->getMetadata()))) - ->setValue('type', $qb->createNamedParameter($signatory->getType()->value)) - ->setValue('status', $qb->createNamedParameter($signatory->getStatus()->value)) - ->setValue('creation', $qb->createNamedParameter(time())) - ->setValue('last_updated', $qb->createNamedParameter(time())); - - $qb->executeStatement(); + private function insertSignatory(Signatory $signatory): void { + $this->mapper->insert($signatory); } /** - * @param ISignatory $signatory + * @param Signatory $signatory * * @throws SignatoryNotFoundException * @throws SignatoryConflictException */ - private function updateKnownSignatory(ISignatory $signatory): void { + private function updateKnownSignatory(Signatory $signatory): void { $knownSignatory = $this->getStoredSignatory($signatory->getKeyId()); switch ($signatory->getType()) { case SignatoryType::FORGIVABLE: @@ -577,12 +523,12 @@ class SignatureManager implements ISignatureManager { /** * This is called when a remote signatory does not exist anymore * - * @param ISignatory|null $knownSignatory NULL is not known + * @param Signatory|null $knownSignatory NULL is not known * * @throws SignatoryConflictException * @throws SignatoryNotFoundException */ - private function manageDeprecatedSignatory(?ISignatory $knownSignatory): void { + private function manageDeprecatedSignatory(?Signatory $knownSignatory): void { switch ($knownSignatory?->getType()) { case null: // unknown in local database case SignatoryType::FORGIVABLE: // who cares ? @@ -600,38 +546,15 @@ class SignatureManager implements ISignatureManager { } - private function updateSignatoryPublicKey(ISignatory $signatory): void { - $qb = $this->connection->getQueryBuilder(); - $qb->update(self::TABLE_SIGNATORIES) - ->set('signatory', $qb->createNamedParameter($signatory->getPublicKey())) - ->set('last_updated', $qb->createNamedParameter(time())); - - $qb->where( - $qb->expr()->eq('key_id_sum', $qb->createNamedParameter($this->hashKeyId($signatory->getKeyId()))) - ); - $qb->executeStatement(); + private function updateSignatoryPublicKey(Signatory $signatory): void { + $this->mapper->updatePublicKey($signatory); } - private function updateSignatoryMetadata(ISignatory $signatory): void { - $qb = $this->connection->getQueryBuilder(); - $qb->update(self::TABLE_SIGNATORIES) - ->set('metadata', $qb->createNamedParameter(json_encode($signatory->getMetadata()))) - ->set('last_updated', $qb->createNamedParameter(time())); - - $qb->where( - $qb->expr()->eq('key_id_sum', $qb->createNamedParameter($this->hashKeyId($signatory->getKeyId()))) - ); - $qb->executeStatement(); + private function updateSignatoryMetadata(Signatory $signatory): void { + $this->mapper->updateMetadata($signatory); } private function deleteSignatory(string $keyId): void { - $qb = $this->connection->getQueryBuilder(); - $qb->delete(self::TABLE_SIGNATORIES) - ->where($qb->expr()->eq('key_id_sum', $qb->createNamedParameter($this->hashKeyId($keyId)))); - $qb->executeStatement(); - } - - private function hashKeyId(string $keyId): string { - return hash('sha256', $keyId); + $this->mapper->deleteByKeyId($keyId); } } diff --git a/lib/public/OCM/IOCMProvider.php b/lib/public/OCM/IOCMProvider.php index dd36a1c6057..cd2a59ebd5e 100644 --- a/lib/public/OCM/IOCMProvider.php +++ b/lib/public/OCM/IOCMProvider.php @@ -6,11 +6,10 @@ declare(strict_types=1); * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCP\OCM; use JsonSerializable; -use NCU\Security\Signature\Model\ISignatory; +use NCU\Security\Signature\Model\Signatory; use OCP\OCM\Exceptions\OCMArgumentException; use OCP\OCM\Exceptions\OCMProviderException; @@ -124,18 +123,18 @@ interface IOCMProvider extends JsonSerializable { /** * store signatory (public/private key pair) to sign outgoing/incoming request * - * @param ISignatory $signatory + * @param Signatory $signatory * @since 31.0.0 */ - public function setSignatory(ISignatory $signatory): void; + public function setSignatory(Signatory $signatory): void; /** * signatory (public/private key pair) used to sign outgoing/incoming request * - * @return ISignatory|null returns null if no ISignatory available + * @return Signatory|null returns null if no Signatory available * @since 31.0.0 */ - public function getSignatory(): ?ISignatory; + public function getSignatory(): ?Signatory; /** * import data from an array @@ -153,7 +152,7 @@ interface IOCMProvider extends JsonSerializable { * enabled: bool, * apiVersion: '1.0-proposal1', * endPoint: string, - * publicKey: ISignatory|null, + * publicKey: Signatory|null, * resourceTypes: list, diff --git a/lib/unstable/Security/Signature/Enum/SignatoryStatus.php b/lib/unstable/Security/Signature/Enum/SignatoryStatus.php new file mode 100644 index 00000000000..9c77cf9bbc2 --- /dev/null +++ b/lib/unstable/Security/Signature/Enum/SignatoryStatus.php @@ -0,0 +1,25 @@ + $list + * + * @return IOutgoingSignedRequest + * @since 31.0.0 + */ + public function setHeaderList(array $list): IOutgoingSignedRequest; + + /** + * returns ordered list of used headers in the Signature + * + * @return list + * @since 31.0.0 + */ + public function getHeaderList(): array; + + /** + * set algorithm to be used to sign the signature + * + * @param SignatureAlgorithm $algorithm + * + * @return IOutgoingSignedRequest + * @since 31.0.0 + */ + public function setAlgorithm(SignatureAlgorithm $algorithm): IOutgoingSignedRequest; + + /** + * returns the algorithm set to sign the signature + * + * @return SignatureAlgorithm + * @since 31.0.0 + */ + public function getAlgorithm(): SignatureAlgorithm; +} diff --git a/lib/unstable/Security/Signature/ISignatoryManager.php b/lib/unstable/Security/Signature/ISignatoryManager.php index 19ba83a4206..20133de4c9c 100644 --- a/lib/unstable/Security/Signature/ISignatoryManager.php +++ b/lib/unstable/Security/Signature/ISignatoryManager.php @@ -8,7 +8,7 @@ declare(strict_types=1); */ namespace NCU\Security\Signature; -use NCU\Security\Signature\Model\ISignatory; +use NCU\Security\Signature\Model\Signatory; /** * ISignatoryManager contains a group of method that will help @@ -51,10 +51,10 @@ interface ISignatoryManager { * * Used to sign outgoing request * - * @return ISignatory + * @return Signatory * @since 31.0.0 */ - public function getLocalSignatory(): ISignatory; + public function getLocalSignatory(): Signatory; /** * retrieve details and generate signatory from remote instance. @@ -64,8 +64,8 @@ interface ISignatoryManager { * * @param string $remote * - * @return ISignatory|null must be NULL if no signatory is found + * @return Signatory|null must be NULL if no signatory is found * @since 31.0.0 */ - public function getRemoteSignatory(string $remote): ?ISignatory; + public function getRemoteSignatory(string $remote): ?Signatory; } diff --git a/lib/unstable/Security/Signature/ISignatureManager.php b/lib/unstable/Security/Signature/ISignatureManager.php index 1969b970aa6..c614a16cd92 100644 --- a/lib/unstable/Security/Signature/ISignatureManager.php +++ b/lib/unstable/Security/Signature/ISignatureManager.php @@ -13,9 +13,7 @@ use NCU\Security\Signature\Exceptions\IncomingRequestException; use NCU\Security\Signature\Exceptions\SignatoryNotFoundException; use NCU\Security\Signature\Exceptions\SignatureException; use NCU\Security\Signature\Exceptions\SignatureNotFoundException; -use NCU\Security\Signature\Model\IIncomingSignedRequest; -use NCU\Security\Signature\Model\IOutgoingSignedRequest; -use NCU\Security\Signature\Model\ISignatory; +use NCU\Security\Signature\Model\Signatory; /** * ISignatureManager is a service integrated to core that provide tools @@ -99,11 +97,11 @@ interface ISignatureManager { * @param string $host remote host * @param string $account linked account, should be used when multiple signature can exist for the same host * - * @return ISignatory + * @return Signatory * @throws SignatoryNotFoundException if entry does not exist in local database * @since 31.0.0 */ - public function searchSignatory(string $host, string $account = ''): ISignatory; + public function getSignatory(string $host, string $account = ''): Signatory; /** * returns a fully formatted keyId, based on a fix hostname and path diff --git a/lib/unstable/Security/Signature/ISignedRequest.php b/lib/unstable/Security/Signature/ISignedRequest.php new file mode 100644 index 00000000000..be52b06cf66 --- /dev/null +++ b/lib/unstable/Security/Signature/ISignedRequest.php @@ -0,0 +1,128 @@ + $list - * - * @return IOutgoingSignedRequest - * @since 31.0.0 - */ - public function setHeaderList(array $list): IOutgoingSignedRequest; - - /** - * returns ordered list of used headers in the Signature - * - * @return list - * @since 31.0.0 - */ - public function getHeaderList(): array; - - /** - * set algorithm to be used to sign the signature - * - * @param SignatureAlgorithm $algorithm - * - * @return IOutgoingSignedRequest - * @since 31.0.0 - */ - public function setAlgorithm(SignatureAlgorithm $algorithm): IOutgoingSignedRequest; - - /** - * returns the algorithm set to sign the signature - * - * @return SignatureAlgorithm - * @since 31.0.0 - */ - public function getAlgorithm(): SignatureAlgorithm; -} diff --git a/lib/unstable/Security/Signature/Model/ISignatory.php b/lib/unstable/Security/Signature/Model/ISignatory.php deleted file mode 100644 index e77b77e66e5..00000000000 --- a/lib/unstable/Security/Signature/Model/ISignatory.php +++ /dev/null @@ -1,160 +0,0 @@ -addType('providerId', 'string'); + $this->addType('host', 'string'); + $this->addType('account', 'string'); + $this->addType('keyId', 'string'); + $this->addType('keyIdSum', 'string'); + $this->addType('publicKey', 'string'); + $this->addType('metadata', 'json'); + $this->addType('type', 'integer'); + $this->addType('status', 'integer'); + $this->addType('creation', 'integer'); + $this->addType('lastUpdated', 'integer'); + + $this->setKeyId($keyId); + } + + /** + * @param string $keyId + * + * @since 31.0.0 + */ + public function setKeyId(string $keyId): void { + // if set as local (for current instance), we apply some filters. + if ($this->local) { + // to avoid conflict with duplicate key pairs (ie generated url from the occ command), we enforce https as prefix + if (str_starts_with($keyId, 'http://')) { + $keyId = 'https://' . substr($keyId, 7); + } + + // removing /index.php from generated url + $path = parse_url($keyId, PHP_URL_PATH); + if (str_starts_with($path, '/index.php/')) { + $pos = strpos($keyId, '/index.php'); + if ($pos !== false) { + $keyId = substr_replace($keyId, '', $pos, 10); + } + } + } + $this->keyId = $keyId; + $this->keyIdSum = hash('sha256', $keyId); + } + + /** + * @param SignatoryType $type + * @since 31.0.0 + */ + public function setType(SignatoryType $type): void { + $this->type = $type->value; + } + + /** + * @return SignatoryType + * @since 31.0.0 + */ + public function getType(): SignatoryType { + return SignatoryType::from($this->type); + } + + /** + * @param SignatoryStatus $status + * @since 31.0.0 + */ + public function setStatus(SignatoryStatus $status): void { + $this->status = $status->value; + } + + /** + * @return SignatoryStatus + * @since 31.0.0 + */ + public function getStatus(): SignatoryStatus { + return SignatoryStatus::from($this->status); + } + + /** + * update an entry in metadata + * + * @param string $key + * @param string|int|float|bool|array $value + * @since 31.0.0 + */ + public function setMetaValue(string $key, string|int|float|bool|array $value): void { + $this->metadata[$key] = $value; + } + + /** + * @return array + * @since 31.0.0 + */ + public function jsonSerialize(): array { + return [ + 'keyId' => $this->getKeyId(), + 'publicKeyPem' => $this->getPublicKey() + ]; + } +} diff --git a/lib/unstable/Security/Signature/Model/SignatoryStatus.php b/lib/unstable/Security/Signature/Model/SignatoryStatus.php deleted file mode 100644 index 4174102beae..00000000000 --- a/lib/unstable/Security/Signature/Model/SignatoryStatus.php +++ /dev/null @@ -1,25 +0,0 @@ -