Skip to content

Commit

Permalink
feat(ocm): add config key to disable signing
Browse files Browse the repository at this point in the history
Signed-off-by: Maxence Lange <[email protected]>
  • Loading branch information
ArtificialOwl committed Nov 12, 2024
1 parent d459f6f commit 4d9f9f9
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 31 deletions.
12 changes: 9 additions & 3 deletions apps/cloud_federation_api/lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\CloudFederationAPI;

use OC\OCM\OCMSignatoryManager;
use OCP\Capabilities\ICapability;
use OCP\IAppConfig;
use OCP\IURLGenerator;
use OCP\OCM\Exceptions\OCMArgumentException;
use OCP\OCM\IOCMProvider;
use OCP\Security\PublicPrivateKeyPairs\Exceptions\KeyPairException;
use OCP\Security\Signature\Exceptions\SignatoryException;
use Psr\Log\LoggerInterface;

Expand All @@ -22,6 +23,7 @@ class Capabilities implements ICapability {

public function __construct(
private IURLGenerator $urlGenerator,
private IAppConfig $appConfig,
private IOCMProvider $provider,
private readonly OCMSignatoryManager $ocmSignatoryManager,
private readonly LoggerInterface $logger,
Expand Down Expand Up @@ -72,8 +74,12 @@ public function getCapabilities() {

// Adding a public key to the ocm discovery
try {
$this->provider->setSignatory($this->ocmSignatoryManager->getLocalSignatory());
} catch (SignatoryException $e) {
if (!$this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_PUBLICKEY_DISABLED, lazy: true)) {
$this->provider->setSignatory($this->ocmSignatoryManager->getLocalSignatory());
} else {
$this->logger->debug('ocm public key feature disabled');
}
} catch (SignatoryException|KeyPairException $e) {
$this->logger->warning('cannot generate local signatory', ['exception' => $e]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@
*/
#[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)]
class RequestHandlerController extends Controller {
public const APPCONFIG_SIGN_ENFORCED = 'enforce_signed_ocm_request';

public function __construct(
string $appName,
IRequest $request,
Expand Down Expand Up @@ -339,7 +337,7 @@ private function getSignedRequest(): ?IIncomingSignedRequest {
// remote does not support signed request.
// currently we still accept unsigned request until lazy appconfig
// core.enforce_signed_ocm_request is set to true (default: false)
if ($this->appConfig->getValueBool('core', self::APPCONFIG_SIGN_ENFORCED, lazy: true)) {
if ($this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_SIGN_ENFORCED, lazy: true)) {
$this->logger->notice('ignored unsigned request', ['exception' => $e]);
throw new IncomingRequestException('Unsigned request');
}
Expand Down
63 changes: 39 additions & 24 deletions lib/private/Federation/CloudFederationProviderManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use OCP\Federation\ICloudIdManager;
use OCP\Http\Client\IClientService;
use OCP\Http\Client\IResponse;
use OCP\IAppConfig;
use OCP\IConfig;
use OCP\OCM\Exceptions\OCMProviderException;
use OCP\OCM\IOCMDiscoveryService;
Expand All @@ -39,6 +40,7 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
public function __construct(
private IConfig $config,
private IAppManager $appManager,
private IAppConfig $appConfig,
private IClientService $httpClientService,
private ICloudIdManager $cloudIdManager,
private IOCMDiscoveryService $discoveryService,
Expand Down Expand Up @@ -112,12 +114,15 @@ public function sendShare(ICloudFederationShare $share) {
try {
// signing the payload using OCMSignatoryManager before initializing the request
$uri = $ocmProvider->getEndPoint() . '/shares';
$signedPayload = $this->signatureManager->signOutgoingRequestIClientPayload(
$this->signatoryManager,
array_merge($this->getDefaultRequestOptions(), ['body' => json_encode($share->getShare())]),
'post', $uri
);
$response = $client->post($uri, $signedPayload);
$payload = array_merge($this->getDefaultRequestOptions(), ['body' => json_encode($share->getShare())]);
if (!$this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_PUBLICKEY_DISABLED, lazy: true)) {
$signedPayload = $this->signatureManager->signOutgoingRequestIClientPayload(
$this->signatoryManager,
$payload,
'post', $uri
);
}
$response = $client->post($uri, $signedPayload ?? $payload);

if ($response->getStatusCode() === Http::STATUS_CREATED) {
$result = json_decode($response->getBody(), true);
Expand Down Expand Up @@ -150,12 +155,16 @@ public function sendCloudShare(ICloudFederationShare $share): IResponse {
try {
// signing the payload using OCMSignatoryManager before initializing the request
$uri = $ocmProvider->getEndPoint() . '/shares';
$signedPayload = $this->signatureManager->signOutgoingRequestIClientPayload(
$this->signatoryManager,
array_merge($this->getDefaultRequestOptions(), ['body' => json_encode($share->getShare())]),
'post', $uri
);
return $client->post($uri, $signedPayload);
$payload = array_merge($this->getDefaultRequestOptions(), ['body' => json_encode($share->getShare())]);
if (!$this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_PUBLICKEY_DISABLED, lazy: true)) {
$signedPayload = $this->signatureManager->signOutgoingRequestIClientPayload(
$this->signatoryManager,
$payload,
'post', $uri
);
}

return $client->post($uri, $signedPayload ?? $payload);
} catch (\Throwable $e) {
$this->logger->error('Error while sending share to federation server: ' . $e->getMessage(), ['exception' => $e]);
try {
Expand Down Expand Up @@ -184,12 +193,15 @@ public function sendNotification($url, ICloudFederationNotification $notificatio

// signing the payload using OCMSignatoryManager before initializing the request
$uri = $ocmProvider->getEndPoint() . '/notifications';
$signedPayload = $this->signatureManager->signOutgoingRequestIClientPayload(
$this->signatoryManager,
array_merge($this->getDefaultRequestOptions(), ['body' => json_encode($notification->getMessage())]),
'post', $uri
);
$response = $client->post($uri, $signedPayload);
$payload = array_merge($this->getDefaultRequestOptions(), ['body' => json_encode($notification->getMessage())]);
if (!$this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_PUBLICKEY_DISABLED, lazy: true)) {
$signedPayload = $this->signatureManager->signOutgoingRequestIClientPayload(
$this->signatoryManager,
$payload,
'post', $uri
);
}
$response = $client->post($uri, $signedPayload ?? $payload);

if ($response->getStatusCode() === Http::STATUS_CREATED) {
$result = json_decode($response->getBody(), true);
Expand All @@ -216,12 +228,15 @@ public function sendCloudNotification(string $url, ICloudFederationNotification
try {
// signing the payload using OCMSignatoryManager before initializing the request
$uri = $ocmProvider->getEndPoint() . '/notifications';
$signedPayload = $this->signatureManager->signOutgoingRequestIClientPayload(
$this->signatoryManager,
array_merge($this->getDefaultRequestOptions(), ['body' => json_encode($notification->getMessage())]),
'post', $uri
);
return $client->post($uri, $signedPayload);
$payload = array_merge($this->getDefaultRequestOptions(), ['body' => json_encode($notification->getMessage())]);
if (!$this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_PUBLICKEY_DISABLED, lazy: true)) {
$signedPayload = $this->signatureManager->signOutgoingRequestIClientPayload(
$this->signatoryManager,
$payload,
'post', $uri
);
}
return $client->post($uri, $signedPayload ?? $payload);
} catch (\Throwable $e) {
$this->logger->error('Error while sending notification to federation server: ' . $e->getMessage(), ['exception' => $e]);
try {
Expand Down
6 changes: 5 additions & 1 deletion lib/private/OCM/OCMSignatoryManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use OC\Security\Signature\Model\Signatory;
use OCP\IURLGenerator;
use OCP\OCM\Exceptions\OCMProviderException;
use OCP\Security\PublicPrivateKeyPairs\Exceptions\KeyPairConflictException;
use OCP\Security\PublicPrivateKeyPairs\Exceptions\KeyPairNotFoundException;
use OCP\Security\PublicPrivateKeyPairs\IKeyPairManager;
use OCP\Security\Signature\Exceptions\SignatureIdentityNotFoundException;
Expand All @@ -30,6 +31,8 @@
*/
class OCMSignatoryManager implements ISignatoryManager {
public const PROVIDER_ID = 'ocm';
public const APPCONFIG_PUBLICKEY_DISABLED = 'disable_ocm_public_key';
public const APPCONFIG_SIGN_ENFORCED = 'enforce_signed_ocm_request';

public function __construct(
private readonly ISignatureManager $signatureManager,
Expand Down Expand Up @@ -62,8 +65,9 @@ public function getOptions(): array {
/**
* @inheritDoc
*
* @since 31.0.0
* @return ISignatory
* @throws KeyPairConflictException
* @since 31.0.0
*/
public function getLocalSignatory(): ISignatory {
try {
Expand Down

0 comments on commit 4d9f9f9

Please sign in to comment.