Skip to content

v2.0.0

Latest

Choose a tag to compare

@codebyjass codebyjass released this 01 Jun 18:24

Active Cipher Storage 2.0.0

This is a breaking release that simplifies configuration, aligns the Rails integration with the official Active Storage service API, and removes legacy/unfinished APIs.

Highlights

  • Rails integration now uses the canonical ActiveStorage::Service::ActiveCipherStorageService.
  • Active Storage config remains simple: service: ActiveCipherStorage with wrapped_service:.
  • Provider setup is centralized through config.provider and config.provider_options.
  • EnvProvider now receives the actual Base64 encryption key via provider_options[:encryption_key].
  • Large multipart uploads and streaming downloads are documented with clearer memory behavior.
  • Legacy Active Storage adapter aliases and key-rotation APIs were removed.

Breaking Changes

  • Removed ActiveCipherStorage::Adapters::ActiveStorageService.
    Use ActiveStorage::Service::ActiveCipherStorageService through Rails storage.yml.

  • Removed active_cipher_storage/active_storage_integration.
    The engine now loads the Active Storage service directly.

  • Removed global Configuration#chunk_size.
    Pass chunk_size where it is used:

    • storage.yml for the Active Storage service
    • S3Adapter.new(...)
    • EncryptedMultipartUpload.new(...)
    • StreamCipher.new(...)
  • Removed provider-specific config helpers such as aws_kms / env_provider.
    Use provider_options instead.

  • Changed EnvProvider configuration.

    Before:

    config.provider_options[:env_var] = "ACTIVE_CIPHER_MASTER_KEY"

    Now:

    config.provider = :env
    config.provider_options[:encryption_key] = ENV.fetch("ACTIVE_CIPHER_MASTER_KEY")
  • Removed key rotation APIs:

    • ActiveCipherStorage::KeyRotation
    • ActiveCipherStorageService#rekey
    • BlobMetadata.blobs_for
    • BlobMetadata.update_after_rotation
    • provider wrap_data_key / rotate_data_key

Configuration

Environment key provider:

ActiveCipherStorage.configure do |config|
  config.provider = :env
  config.provider_options[:encryption_key] = ENV.fetch("ACTIVE_CIPHER_MASTER_KEY")
end

AWS KMS provider:

ActiveCipherStorage.configure do |config|
  config.provider = "aws:kms"
  config.provider_options[:key_id] = Rails.application.credentials.dig(:aws, :kms_key_id)
  config.provider_options[:region] = "us-east-1"
end

AwsKmsProvider now builds its own Aws::KMS::Client and accepts endpoint, access_key_id, secret_access_key, and encryption_context.

Active Storage

Use the Rails-standard service wrapper:

encrypted_s3:
  service: ActiveCipherStorage
  wrapped_service: s3
  chunk_size: 6291456

The service wraps another Active Storage service, encrypts uploads before storage, and decrypts downloads transparently.

Multipart Uploads And Streaming Downloads

For frontend chunked uploads, use EncryptedMultipartUpload.

The app does not assemble the whole file before uploading. Each frontend chunk is read, encrypted into an authenticated ACS frame, and flushed to S3 multipart upload parts as encrypted bytes accumulate.

For large downloads, use streaming:

s3.stream_decrypted(key) do |chunk|
  response.stream.write(chunk)
end

Avoid get_decrypted for huge files because it buffers the encrypted object before decrypting.

Other Changes

  • Blob metadata failures now rescue StandardError only and re-raise in development.
  • path_for now raises NotImplementedError when the wrapped Active Storage service does not support local paths.
  • The tracked examples/ directory was removed. Local sample apps can still be generated outside git as needed.

Verification

  • RSpec: 120 examples, 0 failures
  • RuboCop: no offenses