クライアント側のフィールドレベル自動暗号化
項目一覧
バージョン4.2以降 MongoDB はクライアント側フィールドレベル暗号化(CSFLE)をサポートしています。 これは、ネットワーク経由で MongoDB に送信する前にアプリケーション内のデータを暗号化できる機能です。 CSFLE を有効にすると、MongoDB 製品は暗号化されていない形式でデータにアクセスできなくなります。
CSFLE は、次のメカニズムを使用してセットアップできます。
自動暗号化: フィールドを暗号化する方法を指定するためのコードを記述しなくても、暗号化された読み取りおよび書込み操作を実行できます。
明示的な暗号化: MongoDB ドライバーの暗号化ライブラリを使用して、暗号化された読み取りおよび書込み操作を実行できます。 アプリケーション全体でこのライブラリを使用して暗号化のロジックを指定する必要があります。
バージョン9.0以降、 Mongoid は CSFLE の自動暗号化機能をサポートしています。 このチュートリアルでは、Mongoid で CSFLE を設定し、使用する方法について説明します。
注意
このチュートリアルでは、すべての CSLFE 機能をカバーするものではありません。 MongoDB CSFLE の詳細については、サーバーのドキュメントを参照してください。
注意
明示的な FLE を使用する場合は、Ruby ドライバーのドキュメントに従ってください。
インストール
必要な依存関係をインストールする方法の詳細については、 ドライバーのドキュメント を参照してください。
アプリケーションで使用されている Ruby ドライバーのバージョンを確認し、以下から適切な手順を選択します。
インストール libmongocrypt
これは 2 つの方法のいずれかで実行できます。
libmongocrypt ヘルパー gem を追加する に渡すか、
Gemfile
リリース アーカイブ をダウンロード
libmongocrypt
LIBMONGOCRYPT_PATH
は、オペレーティング システムに一致するバージョンを抽出し、それに応じて 環境変数を設定します。
自動暗号化共有ライブラリのインストール(Ruby ドライバー2.19 +)
Ruby ドライバー バージョン2.19以降を使用する場合は、サーバー マニュアルの「 Queryable Encryption のための自動暗号化共有ライブラリ」ページの手順に従って、自動暗号化共有ライブラリをインストールする必要があります。
必要な手順は次のとおりです。
[ バージョン ] ドロップダウンから、
x.y.z (current)
(現在のバージョンの最新バージョン)を選択します。[ プラットフォーム ] ドロップダウンで、プラットフォームを選択します。
[ パッケージ ] ドロップダウンで、[
crypt_shared
] を選択します。[ダウンロード] をクリックします。
抽出したら、ライブラリへの完全なパスがmongoid.yml
内で次のように構成されていることを確認します。
development: clients: default: options: auto_encryption_options: extra_options: crypt_shared_lib_path: '/path/to/mongo_crypt_v1.so'
mongocryptd
(Rubyドライバー2.18 以前)をインストールします
古いバージョンの Ruby ドライバーを使用している場合は、 mongocryptd
を手動でインストールする必要があります。 mongocryptd
は MongoDB サーバーのエンタープライズ ビルド(バージョン4.2以上)が事前にパッケージ化されています。 インストール手順については、 MongoDB マニュアルを参照してください。
ffi
Gemfile に を追加する
MongoDB Ruby ドライバーは ffi gem を使用しますlibmongocrypt
: から関数を呼び出します。この gem はドライバーの依存関係ではないため、 Gemfile
に手動で追加する必要があります。
gem 'ffi'
CMK の作成
CMK(Customer Master Key)は、データ暗号化キーを暗号化するために使用されます。 最も簡単な方法は、ローカルに保存された96バイトのキーを使用することです。 次の Ruby コードを使用して、このようなキーを生成できます。
require 'securerandom' SecureRandom.hex(48) # => "f54ab...."
このチュートリアルの後半では、カスタマー マスター キーがCUSTOMER_MASTER_KEY
環境変数から利用できることを前提としています。
警告
ローカル マスターキーの使用は安全ではありません。 マスターキーを作成して保存するには、リモートKMSを使用することをお勧めします。 これを行うには、MongoDB クライアント側暗号化ドキュメントの「リモート マスター キーを設定する」の手順に従います。
マスターキーの作成の詳細については、MongoDB マニュアルの「 カスタマーマスターキーの作成 」セクションを参照してください。
クライアントの構成
自動 CSFLE には、MongoDB クライアント用の追加構成が必要です。 アプリケーションにdefault
クライアントが 1 つだけあると仮定すると、次の内容をmongoid.yml
に追加する必要があります。
development: clients: default: uri: mongodb+srv://user:pass@yourcluster.mongodb.net/blog_development?retryWrites=true&w=majority options: auto_encryption_options: # This key enables automatic encryption key_vault_namespace: 'encryption.__keyVault' # Database and collection to store data keys kms_providers: # Tells the driver where to obtain master keys local: # We use the local key in this tutorial key: "<%= ENV['CUSTOMER_MASTER_KEY'] %>" # Key that we generated earlier extra_options: crypt_shared_lib_path: '/path/to/mongo_crypt_v1.so' # Only if you use the library
データ暗号化キーの作成
データ暗号化キー(DEK)は、MongoDB ドキュメントのフィールドを暗号化するために使用するキーです。 データ暗号化キーは、 CMK で暗号化された Key Vault コレクションに保存します。
Mongoid で DEK を作成するには、次のようにdb:mongoid:encryption:create_data_key
Rake
タスクを使用できます。
rake db:mongoid:encryption:create_data_key Created data key with id: 'KImyywsTQWi1+cFYIHdtlA==' for kms provider: 'local' in key vault: 'encryption.__keyVault'.
必要に応じて、複数の DEK を作成できます。
rake db:mongoid:encryption:create_data_key Created data key with id: 'Vxr5m+5cQISjDOruzZgE0w==' for kms provider: 'local' in key vault: 'encryption.__keyVault'.
DEK の代替名を指定することもできます。 これにより、フィールドの暗号化を設定するときに、DEK を名前で参照できるようになります。 また、実行時にフィールドに DEK を動的に割り当てることもできます。
rake db:mongoid:encryption:create_data_key -- --key-alt-name=my_data_key Created data key with id: 'yjF8hKmKQsqGeFGXlB9Sow==' with key alt name: 'my_data_key' for kms provider: 'local' in key vault: 'encryption.__keyVault'.
暗号化スキーマの設定
これで、暗号化する対象を Mongoid に指示できるようになりました。
class Patient include Mongoid::Document include Mongoid::Timestamps # Tells Mongoid what DEK should be used to encrypt fields of the document # and its embedded documents. encrypt_with key_id: 'KImyywsTQWi1+cFYIHdtlA==' # This field is not encrypted. field :category, type: String # This field is encrypted using AEAD_AES_256_CBC_HMAC_SHA_512-Random # algorithm. field :passport_id, type: String, encrypt: { deterministic: false } # This field is encrypted using AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic # algorithm. field :blood_type, type: String, encrypt: { deterministic: true } # This field is encrypted using AEAD_AES_256_CBC_HMAC_SHA_512-Random # algorithm and using a different data key. field :ssn, type: Integer, encrypt: { deterministic: false, key_id: 'Vxr5m+5cQISjDOruzZgE0w==' } 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 the key which alternate name is 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 がすべてのモデルをロードし、データが読み取られるまたは書き込まれる前に暗号化スキーマが構成されるようになります。
既知の制限
MongoDB CSFLE には、サーバー マニュアルのCSFLE 制限ページに記載されている制限がいくつかあります。 これらの制限は、Mongoid にも適用されます。
Mongoid は
embeds_many
関係の暗号化をサポートしていません。:key_name_field
オプションを使用する場合、フィールドは非決定的なアルゴリズムを使用して暗号化する必要があります。 フィールドを確定的に暗号化するには、代わりに:key_id
オプションを指定する必要があります。
データの操作
CSFLE の自動使用は、多くの状況において透過的です。
注意
以下のコード例では、同じデータベースに接続されているが暗号化されていないMongoClient
である変数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"}
決定的なアルゴリズムを使用して暗号化されたフィールドをクエリできます。 完全一致クエリのみがサポートされます。 詳細については、 サーバーのドキュメントを参照してください。
# We can find documents by deterministically encrypted fields. Patient.where(blood_type: "AB+").to_a # => [#<Patient _id: 6447e34d46ebfd3debdd9c39, category: "ER", passport_id: "123456", blood_type: "AB+", ssn: 98765>]
暗号化キー管理
CMK(カスタマー マスター キー)
Your Customer Master Key is the key you use to encrypt your Data Encryption Keys. MongoDB は、データ暗号化キーの作成時に、指定された CMK を使用してデータ暗号化キーを自動的に暗号化します。
CMK は、CSFLE 内で最も機密性の高いキーです。 CMK が侵害された場合、暗号化されたデータはすべて復号化されます。
重要
CMK(Customer Master Key)がリモート KMS に保存されていることを確認します。
リモート KMS を使用する必要がある理由の詳細については、「 リモート KMSを使用する理由 」を参照してください。
サポートされているすべての KMS プロバイダーのリストを表示するには、「 KMS プロバイダー」ページを参照してください。
- MongoDB CSFLE は、次の KMS(Key Management System)プロバイダーをサポートしています。
任意の KMIP 準拠キー管理システム
ローカル キー プロバイダー(テスト専用)
データ暗号化キー
データ暗号化キーは、 db:mongoid:encryption:create_data_key
Rake
タスクを使用して作成できます。 デフォルトでは、これらは データベースと同じクラスターに保存されます。 ただし、キーを個別に保存することをお勧めします。 これは、 mongoid.yml
でキーヴォールト クライアントを指定することで実行できます。
development: clients: key_vault: uri: mongodb+srv://user:pass@anothercluster.mongodb.net/blog_development?retryWrites=true&w=majority default: uri: mongodb+srv://user:pass@yourcluster.mongodb.net/blog_development?retryWrites=true&w=majority options: auto_encryption_options: key_vault_client: :key_vault # Client to connect to key vault # ...
暗号化キーのローテーション
Ruby ドライバーのrewrap_many_data_key
メソッドを使用して暗号化のキーをローテーションできます。 このメソッドは複数のデータ暗号化キーを自動的に復号化し、指定された CMK を使用して再暗号化します。 次に、キーヴォールトコレクション内のローテーションされたキーをアップデートします。 この方法では、2 つのオプションの引数に基づいて暗号化のキーをローテーションできます。
ローテーションするキーを指定するために使用されるフィルター。 指定されたフィルターに一致するデータキーがない場合、キーはローテーションされません。 フィルターを省略すると、キーヴォールト コレクション内のすべてのキーがローテーションされます。
新しい CMK を表すオブジェクト。 現在の CMK を使用してデータキーをローテーションするには、このオブジェクトを省略します。
以下は、 Amazon Web Services KMSを使用してキーをローテーションする例です。
# Create a key vault client key_vault_client = Mongo::Client.new('mongodb+srv://user:pass@yourcluster.mongodb.net') # Or, if you declared the key value client in mongoid.yml, use it key_vault_client = Mongoid.client(:key_vault) # 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( {}, # We want to rewrap all keys { provider: 'aws', master_key: { region: 'us-east-2', key: 'arn:aws:kms:us-east-2:...' } } )
既存のプロジェクトへの自動暗号化の追加
MongoDB 自動 CSFLE はインプレース暗号化をサポートします。 既存のデータベースの暗号化を有効にすると、暗号化されていないデータを引き続き読み取ることができます。 データベースに書き込まれるすべてのデータは暗号化されます。 ただし、暗号化が有効になるとすぐに、すべてのクエリ操作で暗号化されたデータが使用されます。
# We assume that there are two documents in the database, one created without # encryption enabled, and one with encryption. # We can still read both. 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>] # But when we query, we can see only the latter one. Patient.where(blood_type: 'AB+').to_a # => [#<Patient _id: 644937c946ebfd029309b912, category: "ER", passport_id: "AT-1545", blood_type: "AB+", ssn: 987654>]
既存のデータベースを暗号化する場合は、変更がなくてもすべてのデータを読み取って書き戻すことで実行できます。 実行する場合は、次の点に注意してください。
一貫した忠実性のために既存データの整合性を検証します。 CSFLE は型を区別します。たとえば、
String
と宣言されているフィールドでは整数は保存できません。文字列の場合、空の値は常に空の string または設定されていないだけで、
nil
ではないことを確認します(CSFLE はネイティブnull
をサポートしていません)。この操作にはアプリケーションのダウンタイムが必要です。