Корректная конфигурация S3 + Cloudfront CORS?

Мое приложение хранит изображения на S3, а затем передает их через Cloudfront. Я рад использовать новую поддержку S3 CORS, чтобы я мог использовать методы холста HTML5 (которые имеют перекрестную политику происхождения), но, похоже, не могу правильно настроить мой S3 и Cloudfront. При попытке преобразовать изображение в элемент холста все еще работает сообщение "Uncaught Error: SECURITY_ERR: DOM Exception 18".

Вот что у меня так далеко:

S3

<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>MY_WEBSITE_URL</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
  <CORSRule>
    <AllowedOrigin>MY_CLOUDFRONT_URL</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
    </CORSRule>
  </CORSConfiguration>

CloudFront

происхождения

Origin Protocol Policy: Match Viewer

HTTP Port: 80

HTTPS Port: 443

поведения

Origin: MY_WEBSITE_URL

Object Caching: Use Origin Cache Headers

Forward Cookies: None

Forward Query Strings: Yes

Есть что-то, чего я здесь не хватает?

ОБНОВЛЕНИЕ: Просто попытался изменить заголовки на

<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Host</AllowedHeader>

на основе этого вопроса Amazon S3 CORS (Cross-Origin Resource Sharing) и Firefox междоменная загрузка шрифтов

Все еще не идти.

ОБНОВЛЕНИЕ: БОЛЬШЕ ИНФОРМАЦИИ ПО ЗАПРОСУ

Request
URL:https://d1r5nr1emc2xy5.cloudfront.net/uploaded/BAhbBlsHOgZmSSImMjAxMi8wOS8xMC8xOC81NC80Mi85NC9ncmFzczMuanBnBjoGRVQ/32c0cee8
Request Method:GET
Status Code:200 OK (from cache)

ОБНОВИТЬ

Я думаю, что мой запрос был неверным, поэтому я попытался включить CORS с

img.crossOrigin = '';

но затем изображение не загружается, и я получаю сообщение об ошибке: загрузка образа из разных источников запрещена политикой общего доступа к ресурсам из разных источников.

10 ответов

26 июня 2014 года AWS выпустила корректное поведение Vary: Origin в CloudFront, так что теперь вы просто

  1. Установите конфигурацию CORS для вашей корзины S3, включая

    *

  2. В CloudFront -> Распределение -> Поведения для этого источника используйте параметр "Прямые заголовки: белый список" и белый список заголовка "Источник".

  3. Подождите ~20 минут, пока CloudFront распространит новое правило

Теперь ваш дистрибутив CloudFront должен кэшировать разные ответы (с соответствующими заголовками CORS) для разных заголовков клиента Origin.

Чтобы дополнить ответ @ Бретта. Есть страницы документации AWS, подробно описывающие CORS на CloudFront и CORS на S3.

Шаги подробно описаны ниже:

  1. В вашем S3 ведро перейдите в Разрешения -> Конфигурация CORS
  2. Добавить правила для CORS в редакторе <AllowedOrigin> Правило является важным. Сохраните конфигурацию.
  3. В вашем дистрибутиве CloudFront перейдите к Поведению -> выберите поведение -> Изменить
  4. В зависимости от того, хотите ли вы OPTIONS кешируются ответы или нет, согласно AWS есть два пути:
  • Если вы хотите, чтобы ответы OPTIONS кэшировались, сделайте следующее:
    • Выберите параметры для параметров поведения кэша по умолчанию, которые включают кэширование для ответов OPTIONS.
    • Сконфигурируйте CloudFront для пересылки следующих заголовков: Origin, Access-Control-Request-Headers и Access-Control-Request-Method.
  • Если вы не хотите, чтобы ответы OPTIONS кэшировались, настройте CloudFront для пересылки заголовка Origin вместе с любыми другими заголовками, требуемыми вашим источником

И с этим CORS из CloudFront с S3 должен работать.

2022 ответ:

  1. Перейдите в свою корзину S3 -> Разрешения
  2. Прокрутите вниз до совместного использования ресурсов между источниками (CORS).
  3. Применить политику:
      [
    {
        "AllowedHeaders": [],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

Это позволит получить запрос GET из всех источников. Измените в соответствии с потребностями вашего проекта.

  1. Перейдите в свой дистрибутив CloudFront -> Behaviors -> Edit (в моем случае у меня было только одно Behavior)

  2. Прокрутите вниз до пункта Кэшировать ключ и исходные запросы.

  3. Выберите политику кэширования и политику запроса источника (рекомендуется)

  4. В разделе « Политика запроса источника» — необязательно выберите CORS-CustomOrigin.

  5. Сохранить изменения

Сделанный!

Март 2023 г. — меня это устраивает.

Конфигурация сегмента S3

Политика совместного использования ресурсов между источниками (CORS) для корзины S3 (сведения о корзине > разрешения). РегулироватьAllowedOrigins,AllowedHeadersдля вашего проекта (вы можете использовать*во время тестирования установки).

      [
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

Конфигурация Cloudfront CDN

Перейдите в Дистрибутив Cloudfront > Изменить поведение (в большинстве случаев для каждого дистрибутива существует только один вариант).

ОБНОВЛЕНИЕ: это больше не верно с недавними изменениями в CloudFront. Yippee! Смотрите другие ответы для деталей. Я оставляю это здесь для контекста / истории.

проблема

CloudFront не поддерживает CORS 100%. Проблема в том, как CloudFront кэширует ответ на запрос. Любой другой запрос того же URL-адреса после этого приведет к кешированию запроса независимо от источника. Ключевой частью этого является то, что он включает в себя заголовки ответа от источника.

Первый запрос до того, как CloudFront что-нибудь кэширует Origin: http://example.com имеет заголовок ответа:

Access-Control-Allow-Origin: http://example.com

Второй запрос от Origin: https://example.com (обратите внимание, что это HTTPS, а не HTTP) также имеет заголовок ответа:

Access-Control-Allow-Origin: http://example.com

Потому что это то, что CloudFront кэшировал для URL. Это неверно - консоль браузера (по крайней мере, в Chrome) покажет сообщение о нарушении CORS, и все будет сломано.

Временное решение

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

Так что наши URL будут примерно такими:

http://.../some.png?http_mysite.com
https://.../some.png?https_mysite.com

Это работает, но любой может заставить ваш сайт работать плохо, меняя строки запросов. Это вероятно? Наверное, нет, но отладка этой проблемы - огромная проблема.

Правильный обходной путь - не использовать CloudFront с CORS, пока они полностью не поддерживают CORS.

На практике

Если вы используете CloudFront для CORS, используйте альтернативный метод, который будет работать, когда CORS не работает. Это не всегда вариант, но сейчас я динамически загружаю шрифты с помощью JavaScript. Если основанный на CORS запрос к CloudFront завершается неудачно, я возвращаюсь к серверному прокси-серверу для шрифтов (не для перекрестного источника). Таким образом, вещи продолжают работать, хотя CloudFront каким-то образом получил плохую кешированную запись для шрифта.

Я следовал документации AWS:

Затем я использовал aws cdk, чтобы сделать это за меня. Полный источник здесь: https://github.com/quincycs/quincymitchell.com

      const myBucket = new Bucket(this, 'bucket', {
  bucketName: `prod-${domainName}`,
  cors: [{
    allowedMethods: [HttpMethods.GET],
    allowedOrigins: ['*'],
    allowedHeaders: ['*']
  }],
  enforceSSL: true,
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
  removalPolicy: RemovalPolicy.RETAIN
});
const mycert = Certificate.fromCertificateArn(this, 'certificate', ssmCertArn);

new Distribution(this, 'myDist', {
  defaultBehavior: {
    origin: new S3Origin(myBucket),
    viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
    originRequestPolicy: OriginRequestPolicy.CORS_S3_ORIGIN,
    responseHeadersPolicy: ResponseHeadersPolicy.CORS_ALLOW_ALL_ORIGINS,
    allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS, // needed for cors
    cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS, // needed for cors
  },
  defaultRootObject: 'index.html',
  domainNames: [domainName, `www.${domainName}`],
  certificate: mycert
});

В завершение предыдущего ответа я хотел бы поделиться с AWS шагами по включению CORS. Я нашел это очень полезным, предоставив дополнительные ссылки: https://aws.amazon.com/premiumsupport/knowledge-center/no-access-control-allow-origin-error/

Кроме того, при тестировании изменений, помимо задержки развертывания CloudFront, следует учитывать кеш браузера. Я предлагаю использовать разные сеансы инкогнито при тестировании ваших изменений.

Публикация некоторых нетривиальных конфигураций, которые я сделал, чтобы заставить его работать:

  1. Назначьте пользовательский домен облачному интерфейсу, чтобы пользовательский домен был поддоменом, из которого будет запускаться интерфейс вашего приложения. В случае OP он использует localhost:3000; скорее всего, он тестирует свою настройку разработчика, но он должен развернуть это приложение в каком-то домене: назовем это «myapp.com». Таким образом, он может назначить собственный домен, например cdn.myapp.com, чтобы он указывал на blah.cloudfront.net. Вам нужно будет создать / импортировать собственный сертификат SSL для нового личного домена; сертификат облачного интерфейса по умолчанию не будет работать. См. Это: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html[![введите описание изображения здесь] ]22У первого нет личного домена, поэтому столбец CNAME пуст. У второго есть собственный домен, поэтому он у нас напечатан. Вы можете убедиться, что таким образом ваш личный домен был направлен на распространение облачного интерфейса.
  2. Поведение Cloudfront: я предполагаю, что вы уже настроили группу доверенных ключей, поскольку на данный момент у вас уже есть подписанный файл cookie. ОДНАКО, вам нужно будет создать собственную политику кеширования и политику запросов происхождения. См. Следующие снимки экрана с настраиваемой политикой кеширования:и Политикой запроса источника . Следует отметить, что вам необходимо внести в белый список эти заголовки: Origin, Access-Control-Request-Method, Access-Control-Allow-Origin, Access-Control-Запрос-Заголовки. (Вы могли заметить, что Access-Control-Allow-Origin отсутствует в раскрывающемся списке; просто введите его!). Также разрешите все файлы cookie.
  3. Конфигурация S3 CORS: перейдите в корзину S3 и щелкните вкладку разрешений. Прокрутите вниз до конфигурации CORS. Отказ от ответственности: я просто вставил то, что у меня сработало. Обоснованием этого было то, что в моем сценарии к этому S3 должен был получить доступ либо CDN, либо приложение. Я попытался поставить «*» снисходительно, но политика CORS в Chrome жаловалась на то, что я не могу использовать подстановочную запись в AllowedOrigins!
       [
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "POST",
            "GET",
            "HEAD",
            "DELETE"
        ],
        "AllowedOrigins": [
            "cdn.myapp.com",
            "myapp.com",
            "https://cdn.myapp.com",
            "https://myapp.com"
        ],
        "ExposeHeaders": [
            "ETag"
        ]
    }
]
  1. react-player: я использую response-player, как это (обратите внимание на то, что параметр forceHLS установлен, но он снова специфичен для моего варианта использования. Я думаю, что это не обязательно в целом)
       <ReactPlayer
    className="react-player"
    url={url}
    controls={controls}
    light={light}
    config={
      {
        file: {
          forceHLS: true,
          hlsOptions: {
            xhrSetup: function (xhr, url) {
              xhr.withCredentials = true; // send cookies
            },
          },
        },
      }
    }
    playIcon={<PlayIcon />}
    width="100%"
    height="100%"
  />

Не совсем уверен, в чем ваша проблема, но:

https://forums.aws.amazon.com/thread.jspa?messageID=377513

ответил на некоторые мои проблемы с CORS, S3 и Cloudfront.

Я также обнаружил, что некоторые ресурсы внутри корзины будут возвращаться с правильными заголовками CORS, а некоторые - нет. После аннулирования ресурсов все они вернулись с правильными заголовками, не зная, почему некоторые нуждались в аннулировании, а другие - нет, поскольку они были загружены в одно и то же время, того же типа, то же самое ведро:(

Дополнительной причиной ошибок CORS может быть перенаправление HTTP на HTTPS, настроенное в CloudFront.

Согласно документации, в запросах CORS не разрешены перенаправления на другой источник .

Например, если вы попытаетесь получить доступ к некоторому URL-адресу http://example.com, который имеет правило облачного интерфейса для перенаправления HTTP на HTTPS, вы получите ошибку CORS, поскольку https : //cloudfront.url рассматривается браузером как другое происхождение.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSExternalRedirectNotAllowed

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