lserman / capistrano-elbas

Deploy Rails apps to AWS AutoScale groups
MIT License
96 stars 67 forks source link

Assumed role #29

Closed Systho closed 5 years ago

Systho commented 5 years ago

In our setup developer are authenticated through our company but use a role on client company to deploy on their behalf and on their account.

Therefore we ask our client to create a role for us which we can assume for the intervention we do on their account.

I've added this patch which check for a aws_assumed_role_arn key in capistrano config and if present start a special session.

I do not know how frequent our setup is but I'm sharing the code back with you since your gem basically saved me days of work :)

require 'aws/sts'
require 'elbas/aws/credentials'

Elbas::AWS::Credentials.module_eval do

  def overidden_credentials
    @_credentials ||= begin
      _credentials = {
        access_key_id: fetch(:aws_access_key_id, ENV['AWS_ACCESS_KEY_ID']),
        secret_access_key: fetch(:aws_secret_access_key, ENV['AWS_SECRET_ACCESS_KEY'])
      }

      _credentials.merge! region: fetch(:aws_region) if fetch(:aws_region)
      _credentials
    end
  end

  def credentials
    return @patched_credentials if defined?(@patched_credentials)

    credential_hash = overidden_credentials
    assumed_role_arn = fetch(:aws_assumed_role_arn)

    if assumed_role_arn
      sts = ::AWS::STS.new(credential_hash)
      role_credentials = sts.assume_role(
        role_arn: assumed_role_arn,
        role_session_name: "capistrano-session",
      )
      @patched_credentials = role_credentials[:credentials].merge(region: credential_hash[:region])

    else
      @patched_credentials = credential_hash
    end

    @patched_credentials
  end

end
lserman commented 5 years ago

New version of ELBAS will grab creds from the Capistrano variable aws_credentials if specified, that should allow you to do any custom credentials logic without monkey patching :)

Systho commented 4 years ago

For what it's worth, here is how I do it with the new (v3) version :

set :aws_access_key, ENV['AWS_ACCESS_KEY_ID']
set :aws_secret_key, ENV['AWS_SECRET_ACCESS_KEY']
set :aws_region, ENV['AWS_REGION']
set :assumed_role_arn, ENV['AWS_ASSUMED_ROLE_ARN']

set :aws_credentials, -> {
  aws_access_key = fetch :aws_access_key
  aws_secret_key = fetch :aws_secret_key
  assumed_role_arn = fetch :assumed_role_arn

  sts = if aws_access_key.present?
          dev_credentials = ::Aws::Credentials.new(aws_access_key, aws_secret_key)
          ::Aws::STS::Client.new(credentials: dev_credentials)
        else
          ::Aws::STS::Client.new
        end

  role_credentials = sts.assume_role(
    role_arn: assumed_role_arn,
    role_session_name: "capistrano-session",
  ).to_h

  temp_access_key_id = role_credentials[:credentials][:access_key_id]
  temp_secret_access_key = role_credentials[:credentials][:secret_access_key]
  temp_session_token = role_credentials[:credentials][:session_token]

  ::Aws::Credentials.new(temp_access_key_id, temp_secret_access_key, temp_session_token)
}

it was definitely easier than the previous version !