Предварительно подписанные URL-адреса в Vultr Object Storage с использованием boto3

Я работаю с Vultr довольно долгое время, и когда я хотел сохранить некоторые мультимедийные файлы, я подумал об AWS S3, а Vultr предоставляет совместимый с S3 сервис (Object Storage). Я могу использовать s3cmd CLI для игры со службой, и они указывают на использование boto3 для взаимодействия со службой S3. Я хотел, чтобы у моих объектов были подписанные URL-адреса, но я считаю, что у boto3 есть как имя хоста как константу где-то в коде, и это не может быть изменено из конфигураций, как показано ниже:

      import logging
from django.conf import settings
import boto3
from botocore.exceptions import ClientError
from premarket.models import PreMarket
from .models import SupervisorLogs


class Supervisor():

    def __init__(self) -> None:
        self.bucket_name = settings.BUCKET_NAME
        self.link_expiration = settings.ONE_WEEK
        self.queryset = PreMarket.objects.all()
        # Generate a presigned URL for the S3 object
        self.s3_configs_object = settings.AWS_S3_CREDS
        self.s3_client = boto3.client('s3', **self.s3_configs_object)

    def sign_objects(self):
        for obj in self.queryset:
            try:
                presigned_url = self.create_presigned_url(obj.video_url)
                obj.presigned_url = presigned_url
                obj.save()
            except Exception as e:
                self.supervisor_logs(level="ERROR", message=e, description=e)
                logging.error(e)
        self.supervisor_logs(level="COMPLETE",
                            message="Object URL signing has completed",
                            description="Object URL signing has completed")

    def create_presigned_url(self, object_name):
        """Generate a presigned URL to share an S3 object

        :param object_name: string
        :return: Presigned URL as string. If error, returns None.
        """

        try:
            response = self.s3_client.generate_presigned_url('get_object',
                                                            Params={
                                                                'Bucket': self.bucket_name,
                                                                'Key': object_name},
                                                            ExpiresIn=self.link_expiration)
        except ClientError as e:
            logging.error(e)
            self.supervisor_logs(level="ERROR", message=e, description=e)
            return None

        # The response contains the presigned URL
        return response

    def supervisor_logs(self, message: str = None, level: str = None, description: str = None) -> None:
        SupervisorLogs.objects.create(
            message=message, level=level, description=description)

Учетные данные AWS S3:

      AWS_S3_CREDS = {
    'aws_access_key_id': AWS_ACCESS_KEY_ID,
    'aws_secret_access_key': AWS_SECRET_ACCESS_KEY,
    'region_name': 'ewr',
    'endpoint_url': AWS_BUCKET_HOSTNAME
}

Но Vultr предоставляет другое имя хоста, например:

ewr1.vultrobjects.com

Пример объекта:

https://ewr1.vultrobjects.com/my-s3-bucket/basics/video.mp4

Попытка подписать его с помощью кода, который я написал выше, дает следующее (что не работает):

      https://ewr1.vultrobjects.com/my-s3-bucket/https%3A//ewr1.vultrobjects.com/my-s3-bucket/basics/video.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AccessKeyHere%2F20210706%2Fewr%2Fs3%2Faws4_request&X-Amz-Date=20210706T133319Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=bb7da3183691052ea5b25218ab1fb876fec7053a2b045957fec12cd131393a19

У этого есть несколько проблем на первый взгляд: URL-адрес недействителен, поскольку кажется, что он объединяется, и даже если я вручную удалю его только для целей тестирования, он все равно не сработает.

Vultr не предоставляет никаких документов по этому поводу, поскольку их служба поддержки проинформировала меня. На данный момент мне интересно, как я могу получить доступ к объектам в том виде, в каком они есть (без предварительно подписанных URL-адресов), с помощью только ключа доступа, который все равно не будет работать.

Я не знаю, что мне не хватает, и я надеюсь, что у кого-то есть опыт с этим раньше, поскольку я не мог ничего найти в последние пару дней?

Спасибо за помощь.

1 ответ

В приведенном выше коде вы используете URL-адрес:

       presigned_url = self.create_presigned_url(obj.video_url)

Вы пытались использовать местоположение s3 для создания URL-адреса? Судя по всему, obj.video_url - это https: // ewr1 ...... где, поскольку URL-адрес s3 будет s3: // и может быть лучше использован библиотекой, которую вы используете.

Кроме того, прежде чем выполнять весь цикл для каждого URL-адреса, я бы попробовал что-нибудь ручное, например:

      presigned_url = self.create_presigned_url('s3://ewr1.vultrobjects.com/my-s3-bucket/basics/video.mp4')

Посмотрим, доставит ли это вам какое-нибудь удовольствие

Другие вопросы по тегам