Skip to content

Commit

Permalink
Merge pull request #46367 from nextcloud/backport/46317/stable29
Browse files Browse the repository at this point in the history
[stable29] fix(s3): Don't wait indefinitely for S3 to return
  • Loading branch information
solracsf authored Jul 9, 2024
2 parents bff9081 + aa24a4a commit 263524b
Showing 1 changed file with 37 additions and 29 deletions.
66 changes: 37 additions & 29 deletions lib/private/Files/ObjectStore/S3ConnectionTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
use GuzzleHttp\Promise;
use GuzzleHttp\Promise\RejectedPromise;
use OCP\ICertificateManager;
use OCP\Server;
use Psr\Log\LoggerInterface;

trait S3ConnectionTrait {
Expand Down Expand Up @@ -125,7 +126,11 @@ public function getConnection() {
'signature_provider' => \Aws\or_chain([self::class, 'legacySignatureProvider'], ClientResolver::_default_signature_provider()),
'csm' => false,
'use_arn_region' => false,
'http' => ['verify' => $this->getCertificateBundlePath()],
'http' => [
'verify' => $this->getCertificateBundlePath(),
// Timeout for the connection to S3 server, not for the request.
'connect_timeout' => 5
],
'use_aws_shared_config_files' => false,
];

Expand All @@ -143,35 +148,38 @@ public function getConnection() {
}
$this->connection = new S3Client($options);

if (!$this->connection::isBucketDnsCompatible($this->bucket)) {
$logger = \OC::$server->get(LoggerInterface::class);
$logger->debug('Bucket "' . $this->bucket . '" This bucket name is not dns compatible, it may contain invalid characters.',
['app' => 'objectstore']);
}

if ($this->params['verify_bucket_exists'] && !$this->connection->doesBucketExist($this->bucket)) {
$logger = \OC::$server->get(LoggerInterface::class);
try {
$logger->info('Bucket "' . $this->bucket . '" does not exist - creating it.', ['app' => 'objectstore']);
if (!$this->connection::isBucketDnsCompatible($this->bucket)) {
throw new \Exception("The bucket will not be created because the name is not dns compatible, please correct it: " . $this->bucket);
}
$this->connection->createBucket(['Bucket' => $this->bucket]);
$this->testTimeout();
} catch (S3Exception $e) {
$logger->debug('Invalid remote storage.', [
'exception' => $e,
'app' => 'objectstore',
]);
if ($e->getAwsErrorCode() !== "BucketAlreadyOwnedByYou") {
throw new \Exception('Creation of bucket "' . $this->bucket . '" failed. ' . $e->getMessage());
try {
$logger = Server::get(LoggerInterface::class);
if (!$this->connection::isBucketDnsCompatible($this->bucket)) {
$logger->debug('Bucket "' . $this->bucket . '" This bucket name is not dns compatible, it may contain invalid characters.',
['app' => 'objectstore']);
}

if ($this->params['verify_bucket_exists'] && !$this->connection->doesBucketExist($this->bucket)) {
try {
$logger->info('Bucket "' . $this->bucket . '" does not exist - creating it.', ['app' => 'objectstore']);
if (!$this->connection::isBucketDnsCompatible($this->bucket)) {
throw new \Exception("The bucket will not be created because the name is not dns compatible, please correct it: " . $this->bucket);
}
$this->connection->createBucket(['Bucket' => $this->bucket]);
$this->testTimeout();
} catch (S3Exception $e) {
$logger->debug('Invalid remote storage.', [
'exception' => $e,
'app' => 'objectstore',
]);
if ($e->getAwsErrorCode() !== 'BucketAlreadyOwnedByYou') {
throw new \Exception('Creation of bucket "' . $this->bucket . '" failed. ' . $e->getMessage());
}
}
}
}

// google cloud's s3 compatibility doesn't like the EncodingType parameter
if (strpos($base_url, 'storage.googleapis.com')) {
$this->connection->getHandlerList()->remove('s3.auto_encode');

// google cloud's s3 compatibility doesn't like the EncodingType parameter
if (strpos($base_url, 'storage.googleapis.com')) {
$this->connection->getHandlerList()->remove('s3.auto_encode');
}
} catch (S3Exception $e) {
throw new \Exception('S3 service is unable to handle request: ' . $e->getMessage());
}

return $this->connection;
Expand Down Expand Up @@ -220,7 +228,7 @@ protected function getCertificateBundlePath(): ?string {
// since we store the certificate bundles on the primary storage, we can't get the bundle while setting up the primary storage
if (!isset($this->params['primary_storage'])) {
/** @var ICertificateManager $certManager */
$certManager = \OC::$server->get(ICertificateManager::class);
$certManager = Server::get(ICertificateManager::class);
return $certManager->getAbsoluteBundlePath();
} else {
return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
Expand Down

0 comments on commit 263524b

Please sign in to comment.