Как расшифровать файл (зашифрованный с помощью aws KMS) при загрузке с aws S3 через Shrine?

Я использую Shrine в своем приложении Rails для загрузки файлов в Amazon S3. Некоторые файлы пользователей связаны с соблюдением GDPR, и мне нужно реализовать шифрование на стороне клиента ([документация Shrine] (https://github.com/shrinerb/shrine/blob/v2.16.0/doc/storage/s3.md#encryption)). В документации Shrine вы можете увидеть информацию о шифровании файлов с помощью AWS KMS, но не информацию о расшифровке.

Как я могу расшифровать файл, если скачиваю его с aws s3?

Вот мой код:

config / initializers / shrine.rb - Здесь я указываю конфиги для Shrine.

require 'shrine'
require 'shrine/storage/s3'
require 'shrine/storage/file_system'

class Shrine
  plugin :activerecord

  class << self
    Aws::S3::Encryption::Client.extend Forwardable
    Aws::S3::Encryption::Client.delegate(
        [:head_object, :get_object, :config, :build_request] => :client
    )

    def s3_options_encrypted
      {
          prefix:            'encrypted',
          region:            ENV['AWS_REGION'],
          bucket:            ENV['AWS_BUCKET_NAME'] ,
          endpoint:          ENV['AWS_ENDPOINT'],
          access_key_id:     ENV['AWS_ACCESS_KEY_ID'],
          secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
          upload_options:    { acl: 'private' },
          client:            Aws::S3::Encryption::Client.new(kms_key_id: ENV['KMS_KEY_ID'])
      }
    end

    def storages
      {
        cache: Shrine::Storage::FileSystem.new('public', prefix: 'cache_files'),
        encrypted: Shrine::Storage::S3.new(**s3_options_encrypted)
      }
    end
  end
end

models / document.rb - Модель

class Document < ApplicationRecord
  include DocumentsUploader::Attachment.new(:file, {store: :encrypted})
end

controllers / downloads_controller.rb - здесь я скачиваю файл и мне нужно его расшифровать.

class DownloadsController < ApplicationController
  def documents
    document = Document.find(id) if Document.exists?(id: params[:id])

    if document.nil? || !document&.file
      redirect_to root_path and return
    end

    temp_file = document.file.download
    name      = "#{document.name}.pdf"
    type      = 'application/pdf'

    send_file temp_file, filename: name, type: type, disposition: 'attachment'
  end
end

person Roman Malkevych    schedule 23.04.2019    source источник


Ответы (1)


Разработчик структуры Shrink помог мне решить проблему в этом чате

Это была ошибка делегации. Я делегировал [:head_object, :get_object, :config, :build_request] :client, но я должен делегировать [:head_object, :delete_object, :config, :build_request]. Правильное делегирование выглядит так:

Aws::S3::Encryption::Client.delegate(
        [:head_object, :delete_object, :config, :build_request] => :client
    )

Aws::S3::Encryption::Client#get_object уже реализован, и именно он выполняет дешифрование, поэтому добавление этого делегата #get_object будет использовать обычный Aws::S3::Client#get_object, который не выполняет никакого дешифрования.

При этом загрузки автоматически расшифровываются.

person Roman Malkevych    schedule 25.04.2019