Docs Menu

クライアントサイドのフィールド レベル暗号化

このガイドでは、クライアント側のフィールドレベル暗号化(CSFLE)を使用してデータを暗号化する方法を学習できます。CSFLE を使用すると、ネットワーク経由でMongoDBに送信する前にアプリケーション内のデータを暗号化できます。 つまり、 MongoDB製品は暗号化されていない形式でデータにアクセスできません。

CSFLE は、次のいずれかのメカニズムを使用してセットアップできます。

  • 自動暗号化: フィールドを暗号化する方法を指定せずに、暗号化された読み取りおよび書込み操作を実行できます

  • 明示的な暗号化:アプリケーション全体で、指定された暗号化ロジックを使用して暗号化された読み取りおよび書込み操作を実行できます。

このガイドでは、 CSFLE を自動暗号化で設定する方法について説明します。 明示的な暗号化の使用の詳細については、 Rubyドライバーのドキュメントの 明示的な暗号化のガイドを参照してください。

Mongoid で CSFLE を使用するには、まず次の依存関係をインストールする必要があります。

  • libmongocrypt

  • Rubyドライバー v2.19 以降を使用している場合は、 自動暗号化共有ライブラリ が表示されます。 Rubyドライバー v2.18 またはそれ以前のバージョンを使用している場合は、または mongocryptd

  • ffi

次のセクションでは、これらの依存関係をインストールする方法の詳細を説明します。

libmongocryptは、libmongocrypt-ヘルパー gem を Gemfileに追加するか、ライブラリを手動でダウンロードすることでインストールできます。

gemファイルを追加して libmongocrypt をインストールするには、アプリケーションが配置されているフォルダーに移動し、 シェルで次のコマンドを実行します。

gem install libmongocrypt-helper --pre

注意

libmongocrypt-helper のバージョン番号には、 Rubyのリリース前バージョンを示す文字が含まれている場合があるため、--pre フラグが必要です。

ライブラリを手動でダウンロードしてインストールする方法については、 Rubyドライバーのドキュメントの libmongocrypt インストールガイドを参照してください。

次の手順では、自動暗号化共有ライブラリをインストールする方法を詳しく説明します。

  1. ブラウザで、 MongoDBダウンロード センターに移動します。

  2. Version ドロップダウンで、(current) タグで示される現在のバージョンを選択します。

  3. [Platform ドロップダウンでプラットフォームを選択します。

  4. [Package ドロップダウンで crypt_shared を選択します。

  5. 共有ライブラリをダウンロードするには、Download ボタンをクリックします。

ファイルをダウンロードしたら、内容を抽出し、アプリケーションがアクセスできるロケーションにファイルを保存します。 次に、次の例に示すように、アプリケーション内の mongoid.ymlファイルをライブラリを点ように構成します。

development:
clients:
default:
options:
auto_encryption_options:
extra_options:
crypt_shared_lib_path: '<Path to Shared Library>'

Rubyドライバー バージョン 2.18 またはそれ以前のバージョンを使用している場合は、自動暗号化共有ライブラリの代わりに mongocryptd を使用する必要があります。 mongocryptd はMongoDB Serverのエンタープライズ ビルドに事前にパッケージ化されています。 mongocryptdをインストールして構成する方法については、 MongoDB Serverマニュアルの「 mongocryptd のインストール 」ガイドを参照してください。

Mongoid は ffi gem を使用して、libmongocrypt からの関数を呼び出します。シェルで次のコマンドを実行中て、Gemfile に gem を追加します。

gem 'ffi'

データを暗号化および復号化するには、まず CMK(Customer Master Key)を作成する必要があります。 CMK は、データ暗号化キー(DEK)を暗号化するために使用するキーです。CMK にアクセスしないと、クライアントアプリケーションは暗号化されたデータに関連付けられている DEK を復号化することはできません。

次のRubyコードを実行中と、テスト目的でローカル CMK として使用するローカルに保存されるキーを作成できます。

require 'securerandom'
SecureRandom.hex(48)

警告

実稼働環境でローカル CMK を使用するのは安全ではありません。 本番環境では、リモート KMS を使用して CMK を作成および保存します。

KMS プロバイダーの詳細については、 MongoDB Serverマニュアルの「 KMS プロバイダーガイド 」を参照してください。

CSFLE を実装するようにMongoDBクライアントを構成する必要があります。 CSFLE 用のクライアントを構成するには、次のコードを mongoid.ymlファイルに追加します。

development:
clients:
default:
uri: "<connection string>"
options:
auto_encryption_options: # This key enables automatic encryption
key_vault_namespace: 'encryption.__keyVault' # Database and collection in which to store data keys
kms_providers: # Tells the driver where to obtain master keys
local: # Specifies that the key is local
key: "<Path to your CMK>"
extra_options:
crypt_shared_lib_path: '<Path to Shared Library>' # Only required for Ruby versions 2.19 or later

注意

上記のコード例で、括弧(<>)で囲まれたプレースホルダーを置き換えてください。

データ暗号化キー(DEK)は、ドキュメントのフィールドを暗号化するために使用するキーです。 MongoDB は、 CMK で暗号化された DEK をBSONドキュメントとして Key Vaultコレクションに保存します。 MongoDB、キー管理がクライアント側でカスタマーが管理するため、DEK を復号化することはできません。

Mongoid で DEK を作成するには、次の例に示すように、db:mongoid:encryption:create_data_key レイテンシタスクを使用できます。

rake db:mongoid:encryption:create_data_key

生成するキーの数に応じて前述のコマンドを繰り返すことで、複数の DEK を作成できます。

DEK の代替名を指定することもできます。 これにより、フィールドの暗号化を設定するときに DEK を名前で参照、実行時にフィールドに DEK を動的に割り当てることができます。

次の例では、新しい DEK の生成時に代替名を作成します。

rake db:mongoid:encryption:create_data_key -- --key-alt-name=<custom DEK name>

暗号化するフィールドを指定するには、次の例に示すように、モデルのフィールド定義に encrypt オプションを追加し、deterministic オプションと key_id オプションを指定します。

class Patient
include Mongoid::Document
include Mongoid::Timestamps
encrypt_with key_id: '<data encryption key>'
# This field is not encrypted
field :category, type: String
# This field is encrypted by using AEAD_AES_256_CBC_HMAC_SHA_512-Random
# algorithm
field :passport_id, type: String, encrypt: {
deterministic: false
}
# This field is encrypted by using AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic
# algorithm
field :blood_type, type: String, encrypt: {
deterministic: true
}
# This field is encrypted by using AEAD_AES_256_CBC_HMAC_SHA_512-Random
# algorithm and a different data key
field :ssn, type: Integer, encrypt: {
deterministic: false, key_id: '<New key ID'
}
embeds_one :insurance
end
class Insurance
include Mongoid::Document
include Mongoid::Timestamps
field :insurer, type: String
# This field is encrypted using AEAD_AES_256_CBC_HMAC_SHA_512-Random
# algorithm using a key with an alternate name stored in the policy_number_key field
field :policy_number, type: Integer, encrypt: {
deterministic: false,
key_name_field: :policy_number_key
}
embedded_in :patient
end

注意

Railsアプリケーションを開発している場合は、mongoid.ymlファイルで preload_models オプションを true に設定することをお勧めします。 これにより、Mongoid はすべてのモデルをロードし、データが読み取られるまたは書き込まれる前に暗号化スキーマを構成するようになります。

Mongoid で CSFLE を使用する場合、次の制限が適用されます。

  • Mongoid は embeds_many 関連付けの暗号化をサポートしていません。

  • :key_name_field オプションを使用する場合は、 非決定的なアルゴリズム を使用してフィールドを暗号化する必要があります。 フィールドを確定的に暗号化するには、代わりに :key_id オプションを指定する必要があります。

  • MongoDB Serverマニュアルの CSFLE 制限 ページに記載されている制限は、Mongoid にも適用されます。

通常、自動 CSFLE はアプリケーション内で透過的に機能します。 アプリケーションが CSFLE 用に構成されたら、通常どおりドキュメントを作成できます。Mongoid は構成に応じてそれらを自動的に暗号化および復号化します。

次の例では、 CSFLE 用に構成されたアプリケーションに新しい Patientドキュメントを作成します。 次に、データベースに接続されているが CSFLE 用に構成されていない unencrypted_client というクライアントを使用して、ドキュメントを読み取ります。

Patient.create!(
category: 'ER',
passport_id: '123456',
blood_type: 'AB+',
ssn: 98765,
insurance: Insurance.new(insurer: 'TK', policy_number: 123456, policy_number_key: 'my_data_key')
)
# Fields are encrypted in the database
unencrypted_client['patients'].find.first
{"_id"=>BSON::ObjectId('6446a1d046ebfd701f9f4292'),
"category"=>"ER",
"passport_id"=><BSON::Binary:0x404080 type=ciphertext data=0x012889b2cb0b1341...>,
"blood_type"=><BSON::Binary:0x404560 type=ciphertext data=0x022889b2cb0b1341...>,
"ssn"=><BSON::Binary:0x405040 type=ciphertext data=0x012889b2cb0b1341...>,
"insurance"=>{"_id"=>BSON::ObjectId('6446a1d046ebfd701f9f4293'),
"insurer"=>"TK", "policy_number"=><BSON::Binary:0x405920 type=ciphertext
data=0x012889b2cb0b1341...>}, "policy_number_key"=>"my_data_key"}

上記の例では、unencrypted_clientクライアントは暗号化されたフィールドを読み取ることができません。 ただし、CSFLE 用に構成されたクライアントを使用してドキュメントをクエリすると、Mongoid はフィールドを自動的に復号化します。

rewrap_many_data_key Rubyドライバー メソッドを使用して暗号化のキーをローテーションできます。 このメソッドは複数のデータ暗号化キーを自動的に復号化し、指定された CMK を使用して再暗号化します。 次に、 キーヴォールトコレクション内のローテーションされたキーをアップデートします。

rewrap_many_data_key メソッドは次のパラメータを取ります。

  • ローテーションするフィールドを指定するために使用されるフィルター。 指定されたフィルターに一致するデータキーがない場合、キーはローテーションされません。 キーヴォールトコレクション内のすべてのキーをローテーションするには、 フィルターを省略します。

  • DEK を再暗号化するための新しい CMK を表すオブジェクト。 このオブジェクトを省略すると、現在の CMK を使用してデータキーをローテーションできます。

次の例では、 Amazon Web Services KMS を使用して暗号化のキーをローテーションしています。

# Create a key vault client
key_vault_client = Mongo::Client.new('<connection string>')
# Create the encryption object
encryption = Mongo::ClientEncryption.new(
key_vault_client,
key_vault_namespace: 'encryption.__keyVault',
kms_providers: {
aws: {
"accessKeyId": "<IAM User Access Key ID>",
"secretAccessKey": "<IAM User Secret Access Key>"
}
}
)
encryption.rewrap_many_data_key(
{}, # Empty filter to rewrap all keys
{
provider: 'aws',
master_key: {
region: 'us-east-2',
key: 'arn:aws:kms:us-east-2:...'
}
}
)

Mongoid を使用した自動 CSFLE は、インプレース暗号化をサポートします。 既存のデータベースで暗号化を有効にしても、暗号化されていないデータを読み取ることができます。 ただし、暗号化 を有効にすると、新しいデータはすべて暗号化され、クエリ操作では暗号化されたドキュメントのみが使用されます。 つまり、暗号化 を有効にする前に一部のドキュメントが保存されていた場合、クエリではすべてのドキュメントが返されない可能性があります。

次の例では、 1 つの暗号化されたドキュメントと 1 つの暗号化されていないドキュメントを含むコレクションをクエリします。

# Print all documents in the collection. The first document is unencrypted, and
# the second is encrypted.
Patient.all.to_a
# =>
# [#<Patient _id: 644937ac46ebfd02468e58c8, category: "ER", passport_id: "DE-1257", blood_type: "AB+", ssn: 123456>,
# #<Patient _id: 644937c946ebfd029309b912, category: "ER", passport_id: "AT-1545", blood_type: "AB+", ssn: 987654>]
# Querying for documents with a CSFLE-enabled client returns only the encrypted document
Patient.where(blood_type: 'AB+').to_a
# => [#<Patient _id: 644937c946ebfd029309b912, category: "ER", passport_id: "AT-1545", blood_type: "AB+", ssn: 987654>]

CSFLE 対応のクライアントを使用して、すべてのデータを読み取ってから書き戻すことで、コレクション内の既存のデータを暗号化できます。 このときは、既存のすべてのデータが期待されるタイプで、空の値が nil として設定されていないことを確認します。

CSFLE の詳細については、 MongoDB Serverマニュアルの 「クライアント側フィールド レベル暗号化」ガイドを参照してください。

Rubyドライバーで CSFLE を使用する方法の詳細については、 Rubyドライバーのドキュメントの 「クライアント側暗号化のガイド」を参照してください。

アプリケーションで Mongoid を構成する方法の詳細については、「 アプリケーション構成ガイド 」を参照してください。