AzureBlob
Azure Blob client and Active Storage adapter to replace the now abandoned azure-storage-blob
An Active Storage is supplied, but the gem is Rails agnostic and can be used in any Ruby project.
Active Storage
Migration
To migrate from azure-storage-blob to azure-blob:
- Replace
azure-storage-blob
in your Gemfile withazure-blob
- Run
bundle install
- Change the
AzureStorage
service toAzureBlob
in your Active Storage config (config/storage.yml
) - Restart or deploy the app.
Example config:
microsoft:
service: AzureBlob
storage_account_name: account_name
storage_access_key: SECRET_KEY
container: container_name
Managed Identity (Entra ID)
AzureBlob supports managed identities on :
- Azure VM
- App Service
- Azure Functions (Untested but should work)
- Azure Containers (Untested but should work)
AKS support will likely require more work. Contributions are welcome.
To authenticate through managed identities instead of a shared key, omit storage_access_key
from your storage.yml
file and pass in the identity principal_id
.
ActiveStorage config example:
prod:
service: AzureBlob
container: container_name
storage_account_name: account_name
principal_id: 71b34410-4c50-451d-b456-95ead1b18cce
Azurite
To use Azurite, pass the storage_blob_host
config key with the Azurite URL (http://127.0.0.1:10000/devstoreaccount1
by default)
and the Azurite credentials (devstoreaccount1
and Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==
by default).
Example:
dev:
service: AzureBlob
container: container_name
storage_account_name: devstoreaccount1
storage_access_key: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
storage_blob_host: http://127.0.0.1:10000/devstoreaccount1
You'll have to create the container before you can start uploading files. You can do so using Azure CLI, Azure Storage Explorer, or by running:
bin/rails runner "ActiveStorage::Blob.service.client.tap{|client| client.create_container unless client.get_container_properties.present?}.tap { |client| puts 'done!' if client.get_container_properties.present?}"
Make sure that config.active_storage.service = :dev
is set to your azurite configuration.
Container names can't have any special characters, or you'll get an error.
Standalone
Instantiate a client with your account name, an access key and the container name:
client = AzureBlob::Client.new(
account_name: @account_name,
access_key: @access_key,
container: @container,
)
path = "some/new/file"
# Upload
client.create_block_blob(path, "Hello world!")
# Download
client.get_blob(path) #=> "Hello world!"
# Delete
client.delete_blob(path)
For the full list of methods: https://www.rubydoc.info/gems/azure-blob/AzureBlob/Client
options
Lazy loading
The client is configured to raise an error early for missing credentials, causing it to crash before becoming healthy. This behavior can sometimes be undesirable, such as during assets precompilation.
To enable lazy loading and ignore missing credentials, set the lazy
option:
AzureBlob::Client.new(account_name: nil, access_key: nil, container: nil, lazy: true)
or add lazy: true
to your config/storage.yml
for Active Storage.
Contributing
Dev environment
A dev environment is supplied through Nix with devenv.
- Install devenv.
- Enter the dev environment by cd into the repo and running
devenv shell
(ordirenv allow
if you are a direnv user). - Log into azure CLI with
az login
terraform init
-
terraform apply
This will generate the necessary infrastructure on azure. - Generate devenv.local.nix with your private key and container information:
generate-env-file
- If you are using direnv, the environment will reload automatically. If not, exit the shell and reopen it by hitting and running
devenv shell
again.
Entra ID
To test with Entra ID, the AZURE_ACCESS_KEY
environment variable must be unset and the code must be ran or proxied through a VPS with the proper roles.
For cost saving, the terraform variable create_vm
and create_app_service
are false by default.
To create the VPS and App service, Create a var file var.tfvars
containing:
create_vm = true
create_app_service = true
and re-apply terraform: terraform apply -var-file=var.tfvars
.
This will create the VPS and required managed identities.
bin/rake test_azure_vm
and bin/rake test_app_service
will establish a VPN connection to the VM or App service container and run the test suite. You might be prompted for a sudo password when the VPN starts (sshuttle).
After you are done, run terraform again without the var file (terraform apply
) to destroy the VPS and App service application.
Cleanup
Some tests copied over from Rails don't clean after themselves. A rake task is provided to empty your containers and keep cost low: bin/rake flush_test_container
Run without devenv/nix
If you prefer not using devenv/nix:
Ensure your version of Ruby fit the minimum version in azure-blob.gemspec
and setup those Env variables:
AZURE_ACCOUNT_NAME
AZURE_ACCESS_KEY
AZURE_PRIVATE_CONTAINER
AZURE_PUBLIC_CONTAINER
License
The gem is available as open source under the terms of the MIT License.