eodag 3.8.1__py3-none-any.whl → 3.9.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. eodag/api/core.py +1 -1
  2. eodag/api/product/drivers/generic.py +5 -1
  3. eodag/api/product/metadata_mapping.py +132 -35
  4. eodag/cli.py +36 -4
  5. eodag/config.py +5 -2
  6. eodag/plugins/apis/ecmwf.py +3 -1
  7. eodag/plugins/apis/usgs.py +2 -1
  8. eodag/plugins/authentication/aws_auth.py +235 -37
  9. eodag/plugins/authentication/base.py +12 -2
  10. eodag/plugins/authentication/oauth.py +5 -0
  11. eodag/plugins/base.py +3 -2
  12. eodag/plugins/download/aws.py +44 -285
  13. eodag/plugins/download/base.py +3 -2
  14. eodag/plugins/download/creodias_s3.py +1 -38
  15. eodag/plugins/download/http.py +111 -103
  16. eodag/plugins/download/s3rest.py +3 -1
  17. eodag/plugins/manager.py +2 -1
  18. eodag/plugins/search/__init__.py +2 -1
  19. eodag/plugins/search/base.py +2 -1
  20. eodag/plugins/search/build_search_result.py +2 -2
  21. eodag/plugins/search/creodias_s3.py +9 -1
  22. eodag/plugins/search/qssearch.py +3 -1
  23. eodag/resources/ext_product_types.json +1 -1
  24. eodag/resources/product_types.yml +220 -30
  25. eodag/resources/providers.yml +633 -88
  26. eodag/resources/stac_provider.yml +5 -2
  27. eodag/resources/user_conf_template.yml +0 -5
  28. eodag/rest/core.py +8 -0
  29. eodag/rest/errors.py +9 -0
  30. eodag/rest/server.py +8 -0
  31. eodag/rest/stac.py +8 -0
  32. eodag/rest/utils/__init__.py +2 -4
  33. eodag/rest/utils/rfc3339.py +1 -1
  34. eodag/utils/__init__.py +69 -54
  35. eodag/utils/dates.py +204 -0
  36. eodag/utils/s3.py +187 -168
  37. {eodag-3.8.1.dist-info → eodag-3.9.1.dist-info}/METADATA +4 -3
  38. {eodag-3.8.1.dist-info → eodag-3.9.1.dist-info}/RECORD +42 -42
  39. {eodag-3.8.1.dist-info → eodag-3.9.1.dist-info}/entry_points.txt +1 -1
  40. eodag/utils/rest.py +0 -100
  41. {eodag-3.8.1.dist-info → eodag-3.9.1.dist-info}/WHEEL +0 -0
  42. {eodag-3.8.1.dist-info → eodag-3.9.1.dist-info}/licenses/LICENSE +0 -0
  43. {eodag-3.8.1.dist-info → eodag-3.9.1.dist-info}/top_level.txt +0 -0
@@ -21,12 +21,11 @@ import logging
21
21
  import os
22
22
  import re
23
23
  from pathlib import Path
24
- from typing import TYPE_CHECKING, Any, Callable, Literal, Optional, Union, cast
24
+ from typing import TYPE_CHECKING, Any, Literal, Optional, Union, cast
25
25
 
26
26
  import boto3
27
27
  import requests
28
- from botocore.exceptions import ClientError, ProfileNotFound
29
- from botocore.handlers import disable_signing
28
+ from botocore.exceptions import ClientError
30
29
  from lxml import etree
31
30
  from requests.auth import AuthBase
32
31
 
@@ -35,6 +34,7 @@ from eodag.api.product.metadata_mapping import (
35
34
  properties_from_json,
36
35
  properties_from_xml,
37
36
  )
37
+ from eodag.plugins.authentication.aws_auth import raise_if_auth_error
38
38
  from eodag.plugins.download.base import Download
39
39
  from eodag.utils import (
40
40
  DEFAULT_DOWNLOAD_TIMEOUT,
@@ -52,7 +52,6 @@ from eodag.utils import (
52
52
  from eodag.utils.exceptions import (
53
53
  AuthenticationError,
54
54
  DownloadError,
55
- EodagError,
56
55
  MisconfiguredError,
57
56
  NoMatchingProductType,
58
57
  NotAvailableError,
@@ -61,8 +60,8 @@ from eodag.utils.exceptions import (
61
60
  from eodag.utils.s3 import S3FileInfo, open_s3_zipped_object, stream_download_from_s3
62
61
 
63
62
  if TYPE_CHECKING:
63
+ from mypy_boto3_s3 import S3ServiceResource
64
64
  from mypy_boto3_s3.client import S3Client
65
- from mypy_boto3_s3.service_resource import BucketObjectsCollection
66
65
 
67
66
  from eodag.api.product import EOProduct
68
67
  from eodag.api.search_result import SearchResult
@@ -191,13 +190,6 @@ S1_IMG_NB_PER_POLAR = {
191
190
  "VH": {"VH": 1},
192
191
  }
193
192
 
194
- AWS_AUTH_ERROR_MESSAGES = [
195
- "AccessDenied",
196
- "InvalidAccessKeyId",
197
- "SignatureDoesNotMatch",
198
- "InvalidRequest",
199
- ]
200
-
201
193
 
202
194
  class AwsDownload(Download):
203
195
  """Download on AWS using S3 protocol.
@@ -207,8 +199,6 @@ class AwsDownload(Download):
207
199
 
208
200
  * :attr:`~eodag.config.PluginConfig.type` (``str``) (**mandatory**): AwsDownload
209
201
  * :attr:`~eodag.config.PluginConfig.s3_endpoint` (``str``): s3 endpoint url
210
- * :attr:`~eodag.config.PluginConfig.requester_pays` (``bool``): whether download is done
211
- from a requester-pays bucket or not; default: ``False``
212
202
  * :attr:`~eodag.config.PluginConfig.flatten_top_dirs` (``bool``): if the directory structure
213
203
  should be flattened; default: ``True``
214
204
  * :attr:`~eodag.config.PluginConfig.ignore_assets` (``bool``): ignore assets and download
@@ -231,14 +221,11 @@ class AwsDownload(Download):
231
221
 
232
222
  def __init__(self, provider: str, config: PluginConfig) -> None:
233
223
  super(AwsDownload, self).__init__(provider, config)
234
- self.requester_pays = getattr(self.config, "requester_pays", False)
235
- self.s3_session: Optional[boto3.session.Session] = None
236
- self.s3_resource: Optional[boto3.resources.base.ServiceResource] = None
237
224
 
238
225
  def download(
239
226
  self,
240
227
  product: EOProduct,
241
- auth: Optional[Union[AuthBase, S3SessionKwargs]] = None,
228
+ auth: Optional[Union[AuthBase, S3SessionKwargs, S3ServiceResource]] = None,
242
229
  progress_callback: Optional[ProgressCallback] = None,
243
230
  wait: float = DEFAULT_DOWNLOAD_WAIT,
244
231
  timeout: float = DEFAULT_DOWNLOAD_TIMEOUT,
@@ -265,10 +252,6 @@ class AwsDownload(Download):
265
252
  file or with environment variables.
266
253
  :returns: The absolute path to the downloaded product in the local filesystem
267
254
  """
268
- if auth is None:
269
- auth = {}
270
- if isinstance(auth, AuthBase):
271
- raise MisconfiguredError("Please use AwsAuth plugin with AwsDownload")
272
255
 
273
256
  if progress_callback is None:
274
257
  logger.info(
@@ -312,9 +295,14 @@ class AwsDownload(Download):
312
295
  )
313
296
 
314
297
  # authenticate
315
- authenticated_objects, s3_objects = self._do_authentication(
316
- bucket_names_and_prefixes, auth
317
- )
298
+ if product.downloader_auth:
299
+ authenticated_objects = product.downloader_auth.authenticate_objects(
300
+ bucket_names_and_prefixes
301
+ )
302
+ else:
303
+ raise MisconfiguredError(
304
+ "Authentication plugin (AwsAuth) has to be configured if AwsDownload is used"
305
+ )
318
306
 
319
307
  # files in zip
320
308
  updated_bucket_names_and_prefixes = self._download_file_in_zip(
@@ -359,22 +347,28 @@ class AwsDownload(Download):
359
347
  if not os.path.isdir(chunk_abs_path_dir):
360
348
  os.makedirs(chunk_abs_path_dir)
361
349
 
350
+ bucket_objects = authenticated_objects.get(product_chunk.bucket_name)
351
+ extra_args = (
352
+ getattr(bucket_objects, "_params", {}).copy()
353
+ if bucket_objects
354
+ else {}
355
+ )
362
356
  if not os.path.isfile(chunk_abs_path):
363
357
  product_chunk.Bucket().download_file(
364
358
  product_chunk.key,
365
359
  chunk_abs_path,
366
- ExtraArgs=getattr(s3_objects, "_params", {}),
360
+ ExtraArgs=extra_args,
367
361
  Callback=progress_callback,
368
362
  )
369
363
 
370
364
  except AuthenticationError as e:
371
365
  logger.warning("Unexpected error: %s" % e)
372
366
  except ClientError as e:
373
- self._raise_if_auth_error(e)
367
+ raise_if_auth_error(e, self.provider)
374
368
  logger.warning("Unexpected error: %s" % e)
375
369
 
376
370
  # finalize safe product
377
- if build_safe and "S2_MSI" in product.product_type:
371
+ if build_safe and product.product_type and "S2_MSI" in product.product_type:
378
372
  self.finalize_s2_safe_product(product_local_path)
379
373
  # flatten directory structure
380
374
  elif flatten_top_dirs:
@@ -399,11 +393,14 @@ class AwsDownload(Download):
399
393
  """
400
394
  Download file in zip from a prefix like `foo/bar.zip!file.txt`
401
395
  """
402
- if self.s3_resource is None:
396
+ if (
397
+ not getattr(product, "downloader_auth", None)
398
+ or product.downloader_auth.s3_resource is None
399
+ ):
403
400
  logger.debug("Cannot check files in s3 zip without s3 resource")
404
401
  return bucket_names_and_prefixes
405
402
 
406
- s3_client = self.s3_resource.meta.client
403
+ s3_client = product.downloader_auth.get_s3_client()
407
404
 
408
405
  downloaded = []
409
406
  for i, pack in enumerate(bucket_names_and_prefixes):
@@ -577,76 +574,6 @@ class AwsDownload(Download):
577
574
  )
578
575
  return bucket_names_and_prefixes
579
576
 
580
- def _do_authentication(
581
- self,
582
- bucket_names_and_prefixes: list[tuple[str, Optional[str]]],
583
- auth: Optional[Union[AuthBase, S3SessionKwargs]] = None,
584
- ) -> tuple[dict[str, Any], BucketObjectsCollection]:
585
- """
586
- Authenticates with s3 and retrieves the available objects
587
-
588
- :param bucket_names_and_prefixes: list of bucket names and corresponding path prefixes
589
- :param auth: authentication information
590
- :raises AuthenticationError: authentication is not possible
591
- :return: authenticated objects per bucket, list of available objects
592
- """
593
- if not isinstance(auth, (dict, type(None))):
594
- raise AuthenticationError(
595
- f"Incompatible authentication information, expected dict or None, got {type(auth)}"
596
- )
597
- if auth is None:
598
- auth = {}
599
- authenticated_objects: dict[str, Any] = {}
600
- auth_error_messages: set[str] = set()
601
- for _, pack in enumerate(bucket_names_and_prefixes):
602
- try:
603
- bucket_name, prefix = pack
604
- if not prefix:
605
- continue
606
- if bucket_name not in authenticated_objects:
607
- # get Prefixes longest common base path
608
- common_prefix = ""
609
- prefix_split = prefix.split("/")
610
- prefixes_in_bucket = len(
611
- [p for b, p in bucket_names_and_prefixes if b == bucket_name]
612
- )
613
- for i in range(1, len(prefix_split)):
614
- common_prefix = "/".join(prefix_split[0:i])
615
- if (
616
- len(
617
- [
618
- p
619
- for b, p in bucket_names_and_prefixes
620
- if p and b == bucket_name and common_prefix in p
621
- ]
622
- )
623
- < prefixes_in_bucket
624
- ):
625
- common_prefix = "/".join(prefix_split[0 : i - 1])
626
- break
627
- # connect to aws s3 and get bucket auhenticated objects
628
- s3_objects = self.get_authenticated_objects(
629
- bucket_name, common_prefix, auth
630
- )
631
- authenticated_objects[bucket_name] = s3_objects
632
- else:
633
- s3_objects = authenticated_objects[bucket_name]
634
-
635
- except AuthenticationError as e:
636
- logger.warning("Unexpected error: %s" % e)
637
- logger.warning("Skipping %s/%s" % (bucket_name, prefix))
638
- auth_error_messages.add(str(e))
639
- except ClientError as e:
640
- self._raise_if_auth_error(e)
641
- logger.warning("Unexpected error: %s" % e)
642
- logger.warning("Skipping %s/%s" % (bucket_name, prefix))
643
- auth_error_messages.add(str(e))
644
-
645
- # could not auth on any bucket
646
- if not authenticated_objects:
647
- raise AuthenticationError(", ".join(auth_error_messages))
648
- return authenticated_objects, s3_objects
649
-
650
577
  def _get_unique_products(
651
578
  self,
652
579
  bucket_names_and_prefixes: list[tuple[str, Optional[str]]],
@@ -696,20 +623,10 @@ class AwsDownload(Download):
696
623
 
697
624
  return unique_product_chunks
698
625
 
699
- def _raise_if_auth_error(self, exception: ClientError) -> None:
700
- """Raises an error if given exception is an authentication error"""
701
- err = cast(dict[str, str], exception.response["Error"])
702
- if err["Code"] in AWS_AUTH_ERROR_MESSAGES and "key" in err["Message"].lower():
703
- raise AuthenticationError(
704
- f"Please check your credentials for {self.provider}.",
705
- f"HTTP Error {exception.response['ResponseMetadata']['HTTPStatusCode']} returned.",
706
- err["Code"] + ": " + err["Message"],
707
- )
708
-
709
626
  def _stream_download_dict(
710
627
  self,
711
628
  product: EOProduct,
712
- auth: Optional[Union[AuthBase, S3SessionKwargs]] = None,
629
+ auth: Optional[Union[AuthBase, S3SessionKwargs, S3ServiceResource]] = None,
713
630
  byte_range: tuple[Optional[int], Optional[int]] = (None, None),
714
631
  compress: Literal["zip", "raw", "auto"] = "auto",
715
632
  wait: float = DEFAULT_DOWNLOAD_WAIT,
@@ -782,9 +699,14 @@ class AwsDownload(Download):
782
699
  )
783
700
 
784
701
  # authenticate
785
- authenticated_objects, _ = self._do_authentication(
786
- bucket_names_and_prefixes, auth
787
- )
702
+ if product.downloader_auth:
703
+ authenticated_objects = product.downloader_auth.authenticate_objects(
704
+ bucket_names_and_prefixes
705
+ )
706
+ else:
707
+ raise MisconfiguredError(
708
+ "Authentication plugin (AwsAuth) has to be configured if AwsDownload is used"
709
+ )
788
710
 
789
711
  # downloadable files
790
712
  product_objects = self._get_unique_products(
@@ -794,9 +716,13 @@ class AwsDownload(Download):
794
716
  ignore_assets,
795
717
  product,
796
718
  )
797
-
798
- if self.s3_resource is None:
799
- raise EodagError("Cannot check files in s3 zip without s3 resource")
719
+ if auth and isinstance(auth, boto3.resources.base.ServiceResource):
720
+ s3_resource = auth
721
+ else:
722
+ s3_resource = boto3.resource(
723
+ service_name="s3",
724
+ endpoint_url=getattr(self.config, "s3_endpoint", None),
725
+ )
800
726
 
801
727
  product_conf = getattr(self.config, "products", {}).get(
802
728
  product.product_type, {}
@@ -850,7 +776,7 @@ class AwsDownload(Download):
850
776
  zip_filename = sanitize(title)
851
777
 
852
778
  return stream_download_from_s3(
853
- cast("S3Client", self.s3_resource.meta.client),
779
+ cast("S3Client", s3_resource.meta.client),
854
780
  files_info,
855
781
  byte_range,
856
782
  compress,
@@ -867,173 +793,6 @@ class AwsDownload(Download):
867
793
  )
868
794
  return os.path.commonpath(chunk_paths)
869
795
 
870
- def get_rio_env(
871
- self, bucket_name: str, prefix: str, auth_dict: S3SessionKwargs
872
- ) -> dict[str, Any]:
873
- """Get rasterio environment variables needed for data access authentication.
874
-
875
- :param bucket_name: Bucket containg objects
876
- :param prefix: Prefix used to try auth
877
- :param auth_dict: Dictionary containing authentication keys
878
- :returns: The rasterio environement variables
879
- """
880
- rio_env_kwargs = {}
881
- if endpoint_url := getattr(self.config, "s3_endpoint", None):
882
- rio_env_kwargs["endpoint_url"] = endpoint_url.split("://")[-1]
883
- rio_env_kwargs |= auth_dict
884
-
885
- if self.s3_session is None:
886
- _ = self.get_authenticated_objects(bucket_name, prefix, auth_dict)
887
-
888
- if self.s3_session is not None:
889
- if self.requester_pays:
890
- rio_env_kwargs["requester_pays"] = True
891
- return {
892
- "session": self.s3_session,
893
- **rio_env_kwargs,
894
- }
895
- else:
896
- return {"aws_unsigned": True, **rio_env_kwargs}
897
-
898
- def get_authenticated_objects(
899
- self, bucket_name: str, prefix: str, auth_dict: S3SessionKwargs
900
- ) -> BucketObjectsCollection:
901
- """Get boto3 authenticated objects for the given bucket using
902
- the most adapted auth strategy.
903
- Also expose ``s3_session`` as class variable if available.
904
-
905
- :param bucket_name: Bucket containg objects
906
- :param prefix: Prefix used to filter objects on auth try
907
- (not used to filter returned objects)
908
- :param auth_dict: Dictionary containing authentication keys
909
- :returns: The boto3 authenticated objects
910
- """
911
- auth_methods: list[
912
- Callable[[str, str, S3SessionKwargs], Optional[BucketObjectsCollection]]
913
- ] = [
914
- self._get_authenticated_objects_unsigned,
915
- self._get_authenticated_objects_from_auth_profile,
916
- self._get_authenticated_objects_from_auth_keys,
917
- self._get_authenticated_objects_from_env,
918
- ]
919
- # skip _get_authenticated_objects_from_env if credentials were filled in eodag conf
920
- if auth_dict:
921
- del auth_methods[-1]
922
-
923
- for try_auth_method in auth_methods:
924
- try:
925
- s3_objects = try_auth_method(bucket_name, prefix, auth_dict)
926
- if s3_objects:
927
- logger.debug("Auth using %s succeeded", try_auth_method.__name__)
928
- return s3_objects
929
- except ClientError as e:
930
- if (
931
- e.response.get("Error", {}).get("Code", {})
932
- in AWS_AUTH_ERROR_MESSAGES
933
- ):
934
- pass
935
- else:
936
- raise e
937
- except ProfileNotFound:
938
- pass
939
- logger.debug("Auth using %s failed", try_auth_method.__name__)
940
-
941
- raise AuthenticationError(
942
- "Unable do authenticate on s3://%s using any available credendials configuration"
943
- % bucket_name
944
- )
945
-
946
- def _get_authenticated_objects_unsigned(
947
- self, bucket_name: str, prefix: str, auth_dict: S3SessionKwargs
948
- ) -> Optional[BucketObjectsCollection]:
949
- """Auth strategy using no-sign-request"""
950
-
951
- s3_resource = boto3.resource(
952
- service_name="s3", endpoint_url=getattr(self.config, "s3_endpoint", None)
953
- )
954
- s3_resource.meta.client.meta.events.register(
955
- "choose-signer.s3.*", disable_signing
956
- )
957
- objects = s3_resource.Bucket(bucket_name).objects
958
- list(objects.filter(Prefix=prefix).limit(1))
959
- self.s3_resource = s3_resource
960
- return objects
961
-
962
- def _get_authenticated_objects_from_auth_profile(
963
- self, bucket_name: str, prefix: str, auth_dict: S3SessionKwargs
964
- ) -> Optional[BucketObjectsCollection]:
965
- """Auth strategy using RequestPayer=requester and ``aws_profile`` from provided credentials"""
966
-
967
- if "profile_name" in auth_dict.keys():
968
- s3_session = boto3.session.Session(profile_name=auth_dict["profile_name"])
969
- s3_resource = s3_session.resource(
970
- service_name="s3",
971
- endpoint_url=getattr(self.config, "s3_endpoint", None),
972
- )
973
- if self.requester_pays:
974
- objects = s3_resource.Bucket(bucket_name).objects.filter(
975
- RequestPayer="requester"
976
- )
977
- else:
978
- objects = s3_resource.Bucket(bucket_name).objects
979
- list(objects.filter(Prefix=prefix).limit(1))
980
- self.s3_session = s3_session
981
- self.s3_resource = s3_resource
982
- return objects
983
- else:
984
- return None
985
-
986
- def _get_authenticated_objects_from_auth_keys(
987
- self, bucket_name: str, prefix: str, auth_dict: S3SessionKwargs
988
- ) -> Optional[BucketObjectsCollection]:
989
- """Auth strategy using RequestPayer=requester and ``aws_access_key_id``/``aws_secret_access_key``
990
- from provided credentials"""
991
-
992
- if all(k in auth_dict for k in ("aws_access_key_id", "aws_secret_access_key")):
993
- s3_session_kwargs: S3SessionKwargs = {
994
- "aws_access_key_id": auth_dict["aws_access_key_id"],
995
- "aws_secret_access_key": auth_dict["aws_secret_access_key"],
996
- }
997
- if auth_dict.get("aws_session_token"):
998
- s3_session_kwargs["aws_session_token"] = auth_dict["aws_session_token"]
999
- s3_session = boto3.session.Session(**s3_session_kwargs)
1000
- s3_resource = s3_session.resource(
1001
- service_name="s3",
1002
- endpoint_url=getattr(self.config, "s3_endpoint", None),
1003
- )
1004
- if self.requester_pays:
1005
- objects = s3_resource.Bucket(bucket_name).objects.filter(
1006
- RequestPayer="requester"
1007
- )
1008
- else:
1009
- objects = s3_resource.Bucket(bucket_name).objects
1010
- list(objects.filter(Prefix=prefix).limit(1))
1011
- self.s3_session = s3_session
1012
- self.s3_resource = s3_resource
1013
- return objects
1014
- else:
1015
- return None
1016
-
1017
- def _get_authenticated_objects_from_env(
1018
- self, bucket_name: str, prefix: str, auth_dict: S3SessionKwargs
1019
- ) -> Optional[BucketObjectsCollection]:
1020
- """Auth strategy using RequestPayer=requester and current environment"""
1021
-
1022
- s3_session = boto3.session.Session()
1023
- s3_resource = s3_session.resource(
1024
- service_name="s3", endpoint_url=getattr(self.config, "s3_endpoint", None)
1025
- )
1026
- if self.requester_pays:
1027
- objects = s3_resource.Bucket(bucket_name).objects.filter(
1028
- RequestPayer="requester"
1029
- )
1030
- else:
1031
- objects = s3_resource.Bucket(bucket_name).objects
1032
- list(objects.filter(Prefix=prefix).limit(1))
1033
- self.s3_session = s3_session
1034
- self.s3_resource = s3_resource
1035
- return objects
1036
-
1037
796
  def get_product_bucket_name_and_prefix(
1038
797
  self, product: EOProduct, url: Optional[str] = None
1039
798
  ) -> tuple[str, Optional[str]]:
@@ -47,6 +47,7 @@ from eodag.utils.exceptions import (
47
47
  from eodag.utils.notebook import NotebookWidgets
48
48
 
49
49
  if TYPE_CHECKING:
50
+ from mypy_boto3_s3 import S3ServiceResource
50
51
  from requests.auth import AuthBase
51
52
 
52
53
  from eodag.api.product import EOProduct
@@ -103,7 +104,7 @@ class Download(PluginTopic):
103
104
  def download(
104
105
  self,
105
106
  product: EOProduct,
106
- auth: Optional[Union[AuthBase, S3SessionKwargs]] = None,
107
+ auth: Optional[Union[AuthBase, S3SessionKwargs, S3ServiceResource]] = None,
107
108
  progress_callback: Optional[ProgressCallback] = None,
108
109
  wait: float = DEFAULT_DOWNLOAD_WAIT,
109
110
  timeout: float = DEFAULT_DOWNLOAD_TIMEOUT,
@@ -133,7 +134,7 @@ class Download(PluginTopic):
133
134
  def _stream_download_dict(
134
135
  self,
135
136
  product: EOProduct,
136
- auth: Optional[Union[AuthBase, S3SessionKwargs]] = None,
137
+ auth: Optional[Union[AuthBase, S3SessionKwargs, S3ServiceResource]] = None,
137
138
  byte_range: tuple[Optional[int], Optional[int]] = (None, None),
138
139
  compress: Literal["zip", "raw", "auto"] = "auto",
139
140
  wait: float = DEFAULT_DOWNLOAD_WAIT,
@@ -15,17 +15,10 @@
15
15
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
- from typing import TYPE_CHECKING, Optional
19
-
20
- import boto3
21
- from botocore.exceptions import ClientError
18
+ from typing import Optional
22
19
 
23
20
  from eodag import EOProduct
24
21
  from eodag.plugins.download.aws import AwsDownload
25
- from eodag.utils.exceptions import MisconfiguredError
26
-
27
- if TYPE_CHECKING:
28
- from mypy_boto3_s3.service_resource import S3ServiceResource
29
22
 
30
23
 
31
24
  class CreodiasS3Download(AwsDownload):
@@ -42,36 +35,6 @@ class CreodiasS3Download(AwsDownload):
42
35
  verified in requests; default: ``True``
43
36
  """
44
37
 
45
- def _get_authenticated_objects_unsigned(self, bucket_name, prefix, auth_dict):
46
- """Auth strategy using no-sign-request"""
47
-
48
- raise ClientError(
49
- {"Error": {"Code": "AccessDenied", "Message": "skip unsigned"}},
50
- "_get_authenticated_objects_unsigned",
51
- )
52
-
53
- def _get_authenticated_objects_from_auth_keys(self, bucket_name, prefix, auth_dict):
54
- """Auth strategy using RequestPayer=requester and ``aws_access_key_id``/``aws_secret_access_key``
55
- from provided credentials"""
56
-
57
- # check if credentials are missing
58
- required_creds = ["aws_access_key_id", "aws_secret_access_key"]
59
- if not all(auth_dict.get(x, None) for x in required_creds):
60
- raise MisconfiguredError(
61
- f"Incomplete credentials for {self.provider}, missing "
62
- f"{[x for x in required_creds if not auth_dict.get(x, None)]}"
63
- )
64
-
65
- s3_session = boto3.session.Session(**auth_dict)
66
- s3_resource: S3ServiceResource = s3_session.resource(
67
- "s3", endpoint_url=getattr(self.config, "s3_endpoint", None)
68
- )
69
- objects = s3_resource.Bucket(bucket_name).objects.filter()
70
- list(objects.filter(Prefix=prefix).limit(1))
71
- self.s3_session = s3_session
72
- self.s3_resource = s3_resource
73
- return objects
74
-
75
38
  def _get_bucket_names_and_prefixes(
76
39
  self,
77
40
  product: EOProduct,