]> source.dussan.org Git - nextcloud-server.git/commitdiff
fix(s3): Don't wait indefinitely for S3 to return 46366/head
authorGit'Fellow <12234510+solracsf@users.noreply.github.com>
Fri, 5 Jul 2024 08:49:10 +0000 (10:49 +0200)
committerbackportbot[bot] <backportbot[bot]@users.noreply.github.com>
Tue, 9 Jul 2024 07:50:39 +0000 (07:50 +0000)
Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
fix: lint

Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
fix: use AwsException

Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
fix: Throw on connection failure

Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
fix: Wrap all in try catch block

Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
fix: use RequestTimeout error message

Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
log: use OCP Server class

Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
fix: Handle connect timeout only

Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
fix: Handle errors more generically

Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
lib/private/Files/ObjectStore/S3ConnectionTrait.php

index 19fcc5434a00184aa269d9182c60e0f355b15a42..0e887812f85f900543cc8ecf72d0a5b641006e63 100644 (file)
@@ -41,6 +41,7 @@ use Aws\S3\S3Client;
 use GuzzleHttp\Promise;
 use GuzzleHttp\Promise\RejectedPromise;
 use OCP\ICertificateManager;
+use OCP\Server;
 use Psr\Log\LoggerInterface;
 
 trait S3ConnectionTrait {
@@ -149,7 +150,11 @@ trait S3ConnectionTrait {
                        '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,
                ];
 
@@ -167,35 +172,38 @@ trait S3ConnectionTrait {
                }
                $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;
@@ -244,7 +252,7 @@ trait S3ConnectionTrait {
                        // 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';