Поддерживает ли Amazon S3 HTTP-запрос с базовой аутентификацией

Я хотел бы настроить учетную запись Amazon S3, создать корзину, загрузить некоторые данные, и чтобы эти данные были доступны с помощью HTTP GET с базовой аутентификацией.

Я знаю, что существует несколько способов аутентификации данных S3 (строка запроса и т. Д.), Но я хотел бы иметь возможность предоставить простую схему имени пользователя / пароля для аутентификации.

Это возможно?

9 ответов

Теперь это возможно с использованием CloudFront и Lambda@Edge (обычно доступно с июля 2017 года в регионе us-east-1).

  1. Создать ведро S3
  2. Установите дистрибутив CloudFront перед корзиной, ограничив доступ к корзине так, чтобы только CloudFront мог получить к ней доступ напрямую
  3. Создайте лямбда-функцию, которая будет имитировать рукопожатие Basic HTTP Auth с браузером. Назначьте его на CloudFront Viewer Request поведение.

Вот лямбда-функция: https://gist.github.com/lmakarov/e5984ec16a76548ff2b278c06027f1a4

Вот статья с более подробной информацией: https://medium.com/@lmakarov/serverless-password-protecting-a-static-website-in-an-aws-s3-bucket-bfaaa01b8666

Краткий ответ - нет, не используя базовую аутентификацию. Но вот способ, который по сути такой же, как базовая аутентификация, и это проще, чем другие перечисленные решения. Я считаю, что это безопасно, но я не знаю точно.

Вы можете установить условия для блоков s3, которые соответствуют заголовкам по запросу. В качестве примера вы можете использовать useragent, а также referer Заголовки как нечто эквивалентное имени пользователя и паролю в базовой аутентификации. Обычно useragent - это браузер и ОС (вроде Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0)и реферер - предыдущая веб-страница.

Вот пример политики сегмента s3, которая позволяет помещать объекты и получать объекты путем сопоставления useragent и referer (примечание изменено: BUCKETNAME, USERNAME, PASSWORD, AWS_REGION, а также FILENAME к вашим данным):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "allow-username-and-password-access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "s3:PutObject",
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::BUCKETNAME/*",
            "Condition": {
                "StringEquals": {
                    "aws:UserAgent": "USERNAME",
                    "aws:Referer": "PASSWORD"
                }
            }
        }
    ]
}

Чтобы поместить ресурс в корзину, вы можете использовать запрос curl, подобный этому (обратите внимание: BUCKETNAME, USERNAME, PASSWORD, AWS_REGION, а также FILENAME):

curl --user-agent USERNAME --referer PASSWORD --upload-file "FILENAME" --request PUT "https://s3-AWS_REGION.amazonaws.com/BUCKETNAME/FILENAME"

Чтобы использовать ресурс, вы можете использовать что-то вроде этого:

curl --user-agent USERNAME --referer PASSWORD "https://s3-AWS_REGION.amazonaws.com/BUCKETNAME/FILENAME" > FILENAME

Еще раз, я считаю, что это безопасно, так как useragent и referer должны быть зашифрованы, если вы используете https, но, пожалуйста, скажите мне, если это не так.

Вы можете разработать его самостоятельно как веб-приложение или часть существующего приложения. Он будет использовать HTTP-запросы, получать их URI-компонент, преобразовывать его в имя объекта S3 и использовать getObject() для получения его содержимого (используя один из доступных S3 SDK, например AWS Java SDK).

В противном случае вы можете попробовать размещенное решение - http://www.s3auth.com/ (я разработчик). Это проект с открытым исходным кодом, и вы можете увидеть, как этот механизм реализован внутри одного из его основных классов. HTTP-запрос обрабатывается службой, а затем повторно транслируется в схему внутренней аутентификации Amazon S3:

http://s3auth:s3auth@maven.s3auth.com/texry/packages.png

Эта диаграмма архитектуры объясняет, как реализован проект. Изображение PNG загружено из корзины Amazon S3 maven.s3auth.com, который не читается анонимно. Полный URL этого изображения

http://s3auth:s3auth@maven.s3auth.com/texry/packages.png

Посмотрите также эту статью: Базовая аутентификация HTTP для S3 Buckets

Многоуровневое использование сервисов AWS позволяет достичь чего-то близкого к базовой HTTP-авторизации.

  1. Создайте статический сайт s3.
  2. Создайте дистрибутив CloudFront для обслуживания статического сайта s3 (используйте URL статического сайта, а не имя корзины)
  3. Используйте AWS WAF для создания правила, которое разрешает запросы только с правильным заголовком авторизации http. Это будет правило совпадения с содержимым заголовка авторизации.
  4. Используйте Route53 для маршрутизации пользовательского домена в CloudFront Distribution

Теперь у вас должен быть статический сайт, доступ к которому возможен только с правильным именем пользователя и паролем.

ПРИМЕЧАНИЕ: при использовании этой настройки вам не будет предложено ввести ваши учетные данные, так как запрос заблокирован с помощью 403 Запрещено вместо 401 Несанкционировано.

ПРИМЕЧАНИЕ. Вы можете создать дистрибутив CloudFront непосредственно перед корзиной s3, но по умолчанию вы не сможете использовать корневой индексный файл в подпапках.

Нет, это невозможно. Вы должны соответствовать Амазонскому API аутентификации

Проверьте некоторые из упаковщиков, перечисленных здесь.

К настоящему времени это стало относительно просто на AWS. Это в основном 3 вещи, которые нужно сделать:

  1. Создайте функцию CloudFront, чтобы добавить обычную аутентификацию в запрос.
  2. Правильно настройте источник раздачи CloudFront в нескольких местах.
  3. Активируйте функцию CloudFront.

Вот и все, в остальном никаких особых прибамбасов. Вот что я сделал:

Сначала перейдите в CloudFront, затем нажмите «Функции» слева, создайте новую функцию с именем по вашему выбору (без региона и т. д.), а затем добавьте следующее в качестве кода функции:

      function handler(event) {
    
    var user = "myuser";
    var pass = "mypassword";
    
    function encodeToBase64(str) {
        var chars =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        for (
            // initialize result and counter
            var block, charCode, idx = 0, map = chars, output = "";
            // if the next str index does not exist:
            //   change the mapping table to "="
            //   check if d has no fractional digits
            str.charAt(idx | 0) || ((map = "="), idx % 1);
            // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
            output += map.charAt(63 & (block >> (8 - (idx % 1) * 8)))
        ) {
        charCode = str.charCodeAt((idx += 3 / 4));
        if (charCode > 0xff) {
            throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
        );
        }
        block = (block << 8) | charCode;
      }
      return output;
    }
    

    var requiredBasicAuth = "Basic " + encodeToBase64(`${user}:${pass}`);
    var match = false;
    if (event.request.headers.authorization) {
        if (event.request.headers.authorization.value === requiredBasicAuth) {
            match = true;
        }
    }
    
    if (!match) {
      return {
        statusCode: 401,
        statusDescription: "Unauthorized",
        headers: {
          "www-authenticate": { value: "Basic" },
        },
      };
    } 
        
    return event.request;
}

Затем вы можете протестировать непосредственно в пользовательском интерфейсе и, если он работает, и если у вас есть настроенное имя пользователя и пароль, опубликуйте функцию.

Обратите внимание, что я нашел в Интернете отдельные фрагменты вышеприведенной функции, так что это не мой собственный код (кроме того, что я собрал его по кусочкам). Я хотел бы найти источники, чтобы процитировать их здесь, но я больше не могу их найти. Однако заслуга создателей! :-)

Затем откройте раздачу CloudFront и выполните следующие действия:

  1. Убедитесь, что ваша корзина S3 в источнике настроена как конечная точка REST, а не как конечная точка веб-сайта, т. е. она должна заканчиваться .s3.amazonaws.comи не сказать ни слова websiteв имени хоста.
  2. Также в настройках Origin в разделе «Доступ к корзине S3» выберите «Да, использовать OAI (сегмент может ограничить доступ только к CloudFront)». В настройках ниже нажмите «Создать OAI», чтобы создать новый OAI (если у вас нет существующего и вы не знаете, что делаете). И выберите «Да, обновить политику корзины», чтобы позволить AWS добавить необходимые разрешения в ваш OAI.
  3. Наконец, откройте раздел «Поведение дистрибутива CloudFront» и прокрутите вниз. В разделе «Связи функций» для «Запрос средства просмотра» выберите «Функция CloudFront» и выберите только что созданную функцию CloudFront. Сохраните изменения.

И это должно быть так. Если повезет, дело пары минут (на самом деле больше, я знаю) и особенно не дополнительных сложностей, когда все это настроено.

Я сам пытался найти решение этой проблемы. Этот пост здесь перечислил их всех. Цитируя строки:

Я месяцами искал решение для добавления базовой HTTP-аутентификации в корзины S3 на Amazon. Существуют варианты, включающие предварительно подписанные URL-адреса (только для одного объекта), использование сторонних бесплатных или коммерческих услуг (вопросы конфиденциальности), раскрутка EC2/Heroku/ и т. Д. с промежуточным ПО для запросов прокси (сложным и не безсерверным), с использованием перенаправлений страниц и политик сегмента (небезопасно).

Решение для политики Bucket: я лично попробовал это, и оно кажется мне совершенно безопасным (если у вас нет способа обойти политики Bucket AWS). Для работы требуется только ведро s3. Прост в реализации. Основная идея:

  1. Ограничить доступ ко всему сайту, кроме как разрешить публичный доступ к файлу ввода и секретному файлу.
  2. Входной файл secure.html, который принимает пользовательский ввод для пароля и перенаправляет в секретный файл
  3. Секретный файл thisisasecret, который перенаправляет в основной файл (index.html), в котором размещается реальное содержимое сайта.
  4. Основной файл main.html, который разрешает доступ только к запросам, исходящим с того же сайта.
  5. Все остальное содержимое, такое как файлы css, js, будет ограничено политикой сегмента, которая позволит им обслуживаться, если запрос возник из URL вашего сегмента.

Использование aws Lambda@Edge: для этого решения требуются s3, aws lambda и aws cloudfront. Основная идея:

  1. Создайте secure.html. Создать текстовые поля для ввода основных учетных данных от пользователя здесь. Этот файл должен быть общедоступным и должен вызывать лямбда-функцию.
  2. При настройке cloudfront создайте поведение, которое говорит: "если вы хотите получить доступ к index.html, вам нужно сделать это через подписанный URL".
  3. Как и выше, создайте политику сегмента, чтобы разрешить доступ к файлам js, css и т. Д., Только когда источником является ваш URL сегмента.

Посмотрите на мой ответ здесь, в этом несколько связанном вопросе.

Вопрос заключался в том, чтобы получить СПИСОК объектов-контейнеров без необходимости аутентификации S3. Таким образом, из вашего вопроса, мой ответ не совсем объясняет ваш запрос Http-request with basic username/password authentication - но, скорее, дает возможность сделать ведро частным и по-прежнему извлекать его данные, зная identity-pool (ID) и Amazon Resource Name (ARN) (который вы можете считать похожим на имя пользователя и пароль). Конечно, чтобы получить (ID) и (ARN), вы должны выполнить некоторые настройки на главных страницах AWS, как описано в моем 17- шаговом ответе здесь... - а также, это не является частью GET- запрос, а скорее в рамках AWSS3, которые предоставляет Amazon. Я надеюсь, это все еще дает вам больше возможностей для вашего вопроса;)

Я из AdroitLogic. Что касается связанной статьи, она показывает, как UltraESB может быть размещен между вашим клиентом и Amazon S3 для проверки подлинности ваших запросов. При необходимости он может создать службу "прокси", которая будет принимать базовую аутентификацию от вашего клиента и отправлять учетные данные так, как ожидает Amazon S3. Это можно сделать тривиальным способом, и это скроет любую сложность для вашего клиента.

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