Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use Azure Managed Identity for authentication and authorization for Ruby On Rails Active Storage? #233

Open
avivansh opened this issue Jan 22, 2024 · 0 comments

Comments

@avivansh
Copy link

Current setup

azure:
  service: AzureStorage
  storage_account_name: <%= VaultService.get_secret("AZURE-STORAGE::AZURE-STORAGE-ACCOUNT-NAME") %>
  storage_access_key: <%= VaultService.get_secret("AZURE-STORAGE::AZURE-STORAGE-ACCOUNT-ACCESS-KEY") %>
  container: <%= VaultService.get_secret('AZURE-ATTACHMENTS-BUCKET-NAME') %>

Given the implementation of accessing Azure Storage using Access Token. Link

require "azure/storage/common"

access_token = <your initial access token>

# Creating an instance of `Azure::Storage::Common::Core::TokenCredential`
token_credential = Azure::Storage::Common::Core::TokenCredential.new access_token
token_signer = Azure::Storage::Common::Core::Auth::TokenSigner.new token_credential
blob_token_client = Azure::Storage::Blob::BlobService.new(storage_account_name: <your_account_name>, signer: token_signer)

Given the implementation of Active Storage for Ruby on Rails. It uses azure-storage-blob gem under the hood.
link

    def initialize(storage_account_name:, storage_access_key:, container:, public: false, **options)
      @client = Azure::Storage::Blob::BlobService.create(storage_account_name: storage_account_name, storage_access_key: storage_access_key, **options)
      @signer = Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(storage_account_name, storage_access_key)
      @container = container
      @public = public
    end

New Setup, config/storage.yml

azure:
  service: AzureStorage
  storage_account_name: <%= VaultService.get_secret("AZURE-STORAGE::AZURE-STORAGE-ACCOUNT-NAME") %>
  container: <%= VaultService.get_secret('AZURE-ATTACHMENTS-BUCKET-NAME') %>

Monkey patched to use the above information to use active storage using managed identity

module ActiveStorage
  class Service::AzureStorageService < Service
    def initialize(storage_account_name:, container:, public: false, **options)
      access_token = AzureAd::ManagedIdentityTokenProvider.new('https://storage.azure.com/', client_id: ENV['AKS_MANAGED_IDENTITY_ID']).get_authentication_header.split(' ').last
      # Creating an instance of `Azure::Storage::Common::Core::TokenCredential`
      token_credential = ::Azure::Storage::Common::Core::TokenCredential.new access_token
      token_signer = ::Azure::Storage::Common::Core::Auth::TokenSigner.new token_credential
      @client = Azure::Storage::Blob::BlobService.create(storage_account_name: storage_account_name, signer: token_signer, **options)
      user_delegation_key = @client.get_user_delegation_key(DateTime.now - 1.minute, DateTime.now + 6.day + 23.hours)
      @signer = Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(storage_account_name: storage_account_name, user_delegation_key: user_delegation_key )
      @container = container
      @public = public
    rescue StandardError => e
      raise e unless Rake.respond_to?(:application) && (!Rake.application.top_level_tasks.exclude?('assets:precompile') || !Rake.application.top_level_tasks.exclude?('source_map:upload_source_map'))
    end
  end
end

Is this approach correct? (I am yet to test this.). Also, is there any other approach on how to achieve this? I have posted the question on stackoverflow as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant