Ruby: доступ к S3 с профилем экземпляра AWS

У меня есть экземпляр ec2, к которому прикреплен профиль. Я могу использовать awscli, и он отлично выгружается в ведро.

root@ocr-sa-test:/# aws s3 ls s3://company-ocr-east/
                           PRE 7_day_expiry/

root@ocr-sa-test:/# touch foo
root@ocr-sa-test:/# aws s3 cp foo s3://company-ocr-east/foo
upload: ./foo to s3://company-ocr-east/foo
root@ocr-sa-test:/# aws s3 rm s3://company-ocr-east/foo
delete: s3://company-ocr-east/foo

Я не могу заставить его работать с aws-sdk в ruby. Мне отказано в доступе.

irb(main):001:0> require "aws-sdk"
=> true
irb(main):002:0>
irb(main):003:0> credentials = Aws::InstanceProfileCredentials.new
irb(main):004:1* client = Aws::S3::Client.new(
irb(main):005:1*   region: "us-east-1",
irb(main):006:1*   credentials: credentials,
irb(main):007:0> )
irb(main):008:0>
irb(main):009:0>
irb(main):010:0>
irb(main):011:1* begin
irb(main):012:2*   client.put_object(
irb(main):013:2*     key: 'hello.txt',
irb(main):014:2*     body: 'Hello World!',
irb(main):015:2*     bucket: 'company-ocr-east',
irb(main):016:2*     content_type: 'text/plain'
irb(main):017:1*   )
irb(main):018:1* rescue Exception => e
irb(main):019:1*   puts "S3 Upload Error: #{e.class} : Message: #{e.message}"
irb(main):020:0> end
S3 Upload Error: Aws::S3::Errors::AccessDenied : Message: Access Denied

person Mike    schedule 11.11.2020    source источник
comment
это через профиль экземпляра ec2, и он не может использовать локальный файл .aws creds, так как пытается запустить его в kubernetes и не хочет, чтобы ключи api в контейнерах   -  person Mike    schedule 18.11.2020
comment
Если я запускаю credentials = Aws::InstanceProfileCredentials.new и распечатываю объект учетных данных, я вижу временный ключ / секрет со сроком действия   -  person Mike    schedule 18.11.2020
comment
Привет, Майк, вы пытались настроить учетные данные перед созданием клиента? Aws.config.update( credentials: credentials ) Перед тем, как сделать: client = Aws::S3::Client.new( region: "us-east-1" ) Похоже, они рекомендуют сделать это таким образом в документации AWS: docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/ и docs.aws.amazon.com/sdk-for-ruby/v3 / developer-guide /   -  person GuiFalourd    schedule 24.11.2020
comment
@Mike, ваш код работает на моем экземпляре EC2, настроенном аналогично. Библиотека AWS может автоматически создавать учетные данные во время выполнения без явной привязки. Можете ли вы попробовать запустить свой код из строки 11 после создания клиента, например: client = Aws::S3::Client.new(region: "us-east-1")   -  person Amit Singh    schedule 02.01.2021
comment
@Mike Вы смогли решить проблему? Какое было решение?   -  person Scott Swezey    schedule 07.01.2021


Ответы (2)


Эти команды не являются полностью эквивалентными, поэтому будет поучительно определить, что именно в результате отличается на проводе. В частности, SDK получает указание использовать конкретный регион и получать токены STS из IMDS, в то время как CLI остается работать с собственными настройками по умолчанию или с конфигурацией профиля. Кроме того, они не ведут себя одинаково.

Чтобы узнать, что на самом деле происходит, необходимо перезапустить оба с соответствующими флагами отладки, а именно:

aws --debug s3 cp hello.txt s3://bucketname/hello.txt

и

credentials = Aws::InstanceProfileCredentials.new(http_debug_output: $stdout)
client = Aws::S3::Client.new(region: 'us-east-1', credentials: credentials, http_wire_trace: true)
client.put_object(key: 'hello.txt', body: 'Hello World!', bucket: 'bucketname', content_type: 'text/plain')

Они будут генерировать массу вывода, но все это актуально и, что особенно важно, сравнимо, если не обращать внимания на шум. Первое, что нужно проверить, это то, что CLI определенно обращается к IMDS (у него будут запросы к http://169.254.169.254, которые завершаются чем-то вроде найденных учетных данных из роли IAM. Если нет, то экземпляр настроен не так, как вы думали, и в журнале появятся подсказки, объясняющие, как он получает учетные данные , например, неожиданный файл профиля или переменные среды. Вы также захотите проверить, что они получают ту же роль.

Второе, что нужно сравнить, - это последующие последовательности PUT, которые они оба пытаются выполнить. На этом этапе отладки почти все остальное одинаково, поэтому очень вероятно, что вы можете настроить параметры клиента Ruby SDK, чтобы они соответствовали тому, с чем успешно справляется CLI.

Третья возможность - это системный брандмауэр или какие-то средства управления обязательным доступом на уровне процесса, разрешения пользователей, cgroups / контейнеры и т. Д. Однако отладка ядра и конфигурации вашей ОС была бы глубокой темной кроличьей норой, и в любом случае вы сказали, что это экземпляр EC2, так что это, по-видимому, простой старый экземпляр EC2. Если на самом деле приведенные выше команды Ruby выполняются под другим идентификатором пользователя или внутри контейнера, то, возможно, ваш ответ уже есть, это вполне может быть проблема с сетью из-за элементов управления пользователем / контейнером / безопасностью или аналогичной конфигурации уровня ОС, которая требует чинить.

Обязательное предупреждение: если вы решите опубликовать какие-либо данные журнала, будьте осторожны, чтобы перезаписать любые учетные данные! Я не верю, что эти следы отладки особенно воспроизводимы, но вы не хотите выяснять, если я ошибаюсь.

person inopinatus    schedule 30.12.2020

Ошибка отказа в доступе может быть вызвана очень агрессивным таймаутом по умолчанию в Aws::InstanceProfileCredentials.

Попробуйте инициализировать его с более длительным таймаутом или дополнительными попытками:

credentials = Aws::InstanceProfileCredentials.new({
retries: 2,                 # Integer, default: 1
http_open_timeout: 2.5,     # Float, default: 1
http_read_timeout: 2.5      # Float, default: 1
}) 

В документации не уточняется, указаны ли параметры тайм-аута в секундах или другой продолжительности. 2.5 казался консервативным, учитывая значение по умолчанию. Может потребоваться дополнительная настройка.


В документации AWS для API Ruby v3 обсуждается агрессивный тайм-аут в Aws :: S3 :: Client docs, и вы можете увидеть параметры для настройки Aws :: InstanceProfileCredentials.

person Scott Swezey    schedule 28.12.2020