2019年3月21日木曜日

Sidekiq でワーカーにパスワードを渡す場合は暗号化しよう

概要

Sidekiq でジョブをエンキューするときは基本的に平文です
Enterprise Sidekiq であれば Encryption という機能があるのですがフリー版にはありません
そこで Redis にエンキューする際に暗号化する方法を考えます
エンキューする側は Sinatra を想定しています

環境

  • macOS 10.14.3
  • Ruby 2.5.1p57

Base64 にする

かなり単純ですが Base64 にするだけでも一応暗号化できます
エンキューする側で Base64 にエンコードし受け取るワーカー側でデコードします

  • vim app.rb
require 'sinatra/base'
require 'base64'
require 'openssl'
require './worker.rb'

class App < Sinatra::Base
  get '/start' do
    pass = Base64.encode64('password123')
    Worker.perform_async(pass)
  end
end
  • vim worker.rb
require 'sidekiq'
require 'base64'

class Worker
  include Sidekiq::Worker

  def perform(pass)
    puts pass
    puts Base64.decode64(pass)
  end
end

結果的には以下のようにワーカー側で取得できます

cGFzc3dvcmQxMjM=
password123

AES-256-CBC を使う

共通鍵暗号方式です
鍵になる文字列 (key) を使って AES-256-CBC で暗号化したバイト列を作成します
Sidekiq の場合バイト列はワーカーに渡せないので、バイト列を Base64 で文字列にします

  • vim app.rb
require 'sinatra/base'
require 'base64'
require 'openssl'
require './worker.rb'

class App < Sinatra::Base
  get '/start' do
    key = "test_key"
    pass = 'password123'
    encrypted = encrypt(pass, key)
    b64pass = Base64.encode64(encrypted)
    Worker.perform_async(b64pass)
  end

  def encrypt(pass, key)
    enc = OpenSSL::Cipher.new("aes-256-cbc")
    enc.encrypt
    enc.pkcs5_keyivgen(key)
    enc.update(pass) + enc.final
  end
end
  • vim worker.rb
require 'sidekiq'
require 'base64'

class Worker
  include Sidekiq::Worker

  def perform(b64pass)
    key = "test_key"
    puts b64pass
    pass = Base64.decode64(b64pass)
    decrypted = decrypt(pass, key)
    puts decrypted
  end

  def decrypt(pass, key)
    dec = OpenSSL::Cipher.new("aes-256-cbc")
    dec.decrypt
    dec.pkcs5_keyivgen(key)
    dec.update(pass) + dec.final
  end
end

ワーカー側で受け取れる情報は以下の通りです

ZpZtwrsrz6u5XXVHrQiBoA==
password123

こっちのほうがよりセキュアにはなると思います

その他

今回の場合は元の文字列を復号できることが条件になります
なので不可逆なアルゴリズムは使えません
また今回は共通鍵暗号方式になります
Sidekiq のようにワーカーとエンキューする側がシステム内で閉じている場合などは共通鍵暗号方式でいいかなと思います
逆に不特定多数の第三者に対してエンキューする場合などは公開鍵暗号方式のほうがおすすめです

最後に

Sidekiq で Redis に格納する際に暗号化する方法を検討しました
とりあえずパスワードなどが平文で Redis に格納されないだけでも良いかなと思います

今回はエンキューする側が Sinatra のような Web アプリを想定して行いました
もしかするとリクエストにパスワードなどが乗ってくる場合があると思います
そのような場合はすでに暗号化されている可能性があるのでエンキューする側は特に暗号化はせずエンキューしてワーカー側で復号するだけという手段も取れるかなと思います

その辺はシステムの仕様なので好きなように決めればいいかなと思います

参考サイト

0 件のコメント:

コメントを投稿