3

I have kubernetes setup with STS and it works fine with sdk for sqs, sns etc. I need to use STS auth with fog-aws gem to download/list files and I can do it with ruby aws-sdk-s3 but I use carrierwave gem so I am trying to figure it out using fog-aws.

Using sdk - Works

s3 = Aws::S3::Client.new
resp = s3.list_objects(bucket:'sts-s3-test')
<Lists objects successfully>

Using fog-aws - Fails

s3 = Fog::Storage.new(provider: 'AWS', region: 'us-west-2',use_iam_profile: true)
directory = s3.directories.get('sts-s3-test')

Excon::Error::Forbidden (Expected(200) <=> Actual(403 Forbidden)) 
<Error><Code>AccessDenied</Code>

Appreciate any pointers, thanks.

EDIT:

STS is configured by our DevOps in kuberenets using service account https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/. I am not aware of internals and how it works but with this setup new aws sdk can read account details and assumes role automatically, there is no need of explicitly calling assume role functionality. This we can see from my first example for listing s3 objects where I do not pass any credentials. Link to aws sdk new version which uses service-account from pods. https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/

I have tried approach on getting temporary access key & secret and pass it to storage class but that also doesn't work. Our DevOps guy says all access with key & secret are disabled and only way to use it is using assume_role_with_web_identity

I also found gist which I think solves the issue I am having, I am yet to give it a try. Link for ref https://gist.github.com/peterwells/39a5c31d934fa8eb0f2c

pramodtech
  • 5,810
  • 15
  • 65
  • 108

1 Answers1

0

Getting setup based on Fog docs

Since your top-most code sample doesn't show you passing in credentials to the aws sdk client, so if you followed the docs for the aws-sdk-ruby gem, then your credentials are probably located in environment variables (presumably AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY like it shows in the docs).

fog-aws does not implement these environment variables. They have a somewhat backwards way of setting up a configuration. What you have to do is create a .fog file in your home directory (not your project's directory) that contains the following keys and their respective values:

default:
  aws_access_key_id:     <YOUR_ACCESS_KEY_ID>
  aws_secret_access_key: <YOUR_SECRET_ACCESS_KEY>

Once you set that up, hopefully then you should be able to perform your second snippet:

s3 = Fog::Storage.new(provider: 'AWS', region: 'us-west-2',use_iam_profile: true)
directory = s3.directories.get('sts-s3-test')

Tips based on your described environment

The above approach might not work for you since you're working in a kubernetes environment and keeping track of configuration files in your home directory not might not work for you.

If that's the case, then you can specify those values in the call to fog:

s3 = Fog::Storage.new(
  provider: 'AWS',
  region: 'us-west-2',
  aws_access_key_id: 'xxxxx', # or directly from ENV['AWS_ACCESS_KEY_ID']
  aws_secret_access_key: 'xxxxx', # or directly from ENV['AWS_SECRET_ACCESS_KEY']
  use_iam_profile: true
)

Note: There's also been issues reported regarding Fog and the use_iam_profile option, so give those a check out too.


Implementing with CarrierWave

The above approach is helpful for if you're going to make calls to S3 outside of the context of CarrierWave (i.e. if you need to fetch S3 directories in an uploader or controller, for example). If you don't need your code to be aware of that information the above approach isn't really needed because when integrating with CarrierWave, the most common way is specifying your AWS credentials in CarrierWave's initializer.

You need to create a carrierwave.rb in ./config/initializers and specify the credentials that you would have given fog:

# ./config/initializers/carrierwave.rb

## This sample snippet was taken from the carrierwave readme!

CarrierWave.configure do |config|
  config.fog_credentials = {
    provider:              'AWS',                        # required
    aws_access_key_id:     'xxx',                        # required unless using use_iam_profile
    aws_secret_access_key: 'yyy',                        # required unless using use_iam_profile
    use_iam_profile:       true,                         # optional, defaults to false
    region:                'us-west-2',                  # optional, defaults to 'us-east-1'
  }
  config.fog_directory  = 'name_of_bucket'                                      # required
  config.fog_public     = false                                                 # optional, defaults to true
end

I don't have my config values hard coded into my app, I use Rails 6's credentials cability (the equivalent would be secrets for Rails 5 and below).

I hope this helps you, or puts you in the right direction! I recently got tripped up with Fog's configuration setup (particuarly because having it in the home directory didn't work since it was more work for how I wanted to setup my project, which is also a Rails app on kubernetes).

bwalshy
  • 1,013
  • 11
  • 18
  • Thanks @bwalshy, appreciate your detailed response. I realized my question was not descriptive enough, I have updated my question with more details. – pramodtech Jan 06 '20 at 18:15