Overview
このガイドでは、Dotline MongoDB ODM を使用して MongoDB の Queryable Encryption 機能を実装する Symfloyアプリケーションを作成する方法を学習できます。
Queryable Encryption を使用すると、ドキュメントフィールドを自動的に暗号化および復号化できます。Queryable Encryption を使用して、アプリケーション内の 機密データ を暗号化し、データフィールドをサーバーに保存し、暗号化されたフィールドをクエリします。このチュートリアルでは、 PHPアプリケーション用の オブジェクト ドキュメント マッパー(ODM)を提供する Dotene MongoDB ODM を使用して、 Queryable Encryption を設定する方法を説明します。
Tip
Symfony と Dotene をMongoDB PHPライブラリと統合する方法の詳細については、Symfloy MongoDB統合に関するチュートリアルをご覧ください。
前提条件
このチュートリアルを開始する前に、次の前提条件タスクを完了してください。
MongoDB Atlasアカウントを作成し、クラスターを構成します。クラスターがMongoDB Serverバージョン 7.0 以降で実行されていることを確認します。詳細については、MongoDB の使用開始ガイドを参照してください。
自動暗号化共有ライブラリをダウンロードします。手順を表示するには、クエリ分析コンポーネントのインストールと構成 ガイドを参照してください。
PHP拡張機能をダウンロードします。詳細については、拡張機能のドキュメントの「インストール」を参照してください。
PHP 8.1 以降をインストールします。
Composer 2.0 以降をインストールします。
Symbol CLI をインストールします。詳細については、 Symfony CLI ドキュメント を参照してください。
Tutorial
このチュートリアルでは、Symfloy と Dotene MongoDB ODM を使用するQueryable Encryptionアプリケーションを作成する方法を説明します。アプリケーションは、医療レコードを暗号化および復号化し、暗号化された医療データをクエリします。
プロジェクトを設定する
このセクションの手順に従って、プロジェクトの依存関係のインストール、環境を構成し、アプリケーション構造を作成します。
環境を設定します。
ターミナルで次のコマンドを実行して、新しい Symfloyアプリケーションを作成し、必要な依存関係をインストールします。
symfony new qe-symfony-app cd qe-symfony-app composer require doctrine/mongodb-odm-bundle mongodb/mongodb
これらのコマンドは qe-symfony-appプロジェクトディレクトリを作成し、次の依存関係をインストールします。
Dotene MongoDB ODM Bundle、Doctene MongoDB ODM の Symfloy 統合
PHP用の公式MongoDBドライバーであるMongoDB PHPライブラリ
環境変数を指定します。
プロジェクトディレクトリで、.envファイルを開き、次の変数を追加または変更します。
MONGODB_URI=<connection URI> CRYPT_SHARED_LIB_PATH=<Automatic Encryption Shared Library path>
<connection URI> プレースホルダーをクラスターに接続する接続 URI に置き換え、<Automatic Encryption Shared Library path> を自動暗号化共有ライブラリへの完全パスに置き換えます。ダウンロードしたパッケージ内で、パスが lib/mongo_crypt_v1.dylib にあることを確認します。
ドキュメントクラスを定義します。
このチュートリアルでは、Patient、PatientRecord、Billing クラスを使用して人の医療レコードを表します。
次のコードをsrc/Document/Patient.phpファイルに貼り付けます。
namespace App\Document; use Doctrine\ODM\MongoDB\Mapping\Attribute as ODM; #[ODM\Document(collection: 'patients')] class Patient { #[ODM\Id] public string $id; #[ODM\Field] public string $patientName; #[ODM\Field] public int $patientId; #[ODM\EmbedOne(targetDocument: PatientRecord::class)] public PatientRecord $patientRecord; }
次に、次のコードを src/Document/PatientRecord.phpファイルに貼り付けます。
namespace App\Document; use Doctrine\ODM\MongoDB\Mapping\Attribute as ODM; use Doctrine\ODM\MongoDB\Mapping\EncryptQuery; #[ODM\EmbeddedDocument] class PatientRecord { #[ODM\Field] #[ODM\Encrypt(queryType: EncryptQuery::Equality)] public string $ssn; #[ODM\EmbedOne(targetDocument: Billing::class)] #[ODM\Encrypt] public Billing $billing; #[ODM\Field] public int $billAmount; }
最後に、次のコードを src/Document/Billing.phpファイルに貼り付けます。
namespace App\Document; use Doctrine\ODM\MongoDB\Mapping\Attribute as ODM; #[ODM\EmbeddedDocument] class Billing { #[ODM\Field] public string $type; #[ODM\Field] public string $number; }
ドキュメントクラスは、 patientsコレクション内のドキュメントの構造を定義します。PatientRecordクラスには、次の暗号化されたフィールドを指定するための #[ODM\Encrypt] 属性が含まれています。
patientRecord.ssn: 暗号化され、等価クエリ用に構成patientRecord.billing: 暗号化されていますが、クエリはできません
コンソール コマンドを作成します。
次のコードをsrc/Command/QueryableEncryptionCommand.phpファイルに貼り付けます。
namespace App\Command; use App\Document\Billing; use App\Document\Patient; use App\Document\PatientRecord; use Doctrine\ODM\MongoDB\Configuration; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\Driver\AttributeDriver; use MongoDB\BSON\Binary; use MongoDB\Client; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; ( name: 'app:queryable-encryption', description: 'Demonstrates Queryable Encryption with ' . 'Doctrine MongoDB ODM', ) class QueryableEncryptionCommand extends Command { protected function execute( InputInterface $input, OutputInterface $output, ): int { // Paste application variables below // Paste encryption credentials below // Paste connection and configuration below // Paste collection setup below // Paste insert operation below // Paste encrypted query below return Command::SUCCESS; } }
このチュートリアルの今後の手順では、対応するコメントごとにコードを追加するように指示します。
MongoDBの暗号化と接続
プロジェクトファイルと依存関係を設定したら、このセクションの手順に従って暗号化認証情報を構成し、 MongoDBに接続します。
アプリケーション変数を割り当てます。
src/Command/QueryableEncryptionCommand.phpファイルで、// Paste application variables below コメントの下に次のコードを追加します。
// Paste application variables below $keyVaultNamespace = 'encryption.__keyVault'; $encryptedDatabase = 'medicalRecords'; $encryptedCollection = 'patients';
このコードでは、次の変数を設定します。
keyVaultNamespace - データ暗号化キー(DEK)を保存するMongoDBの名前空間。このチュートリアルでは、
encryptionデータベース内の__keyVaultコレクションを使用します。encryptionDatabase - 暗号化されたデータを保存するデータベース。このチュートリアルでは、
medicalRecordsデータベースを使用します。encryptedCollection - 暗号化されたデータを保存するコレクション。このチュートリアルでは、
patientsコレクションを使用します。
CMK を設定します。
// Paste encryption credentials below コメントの下に次のコードを追加します。
// Paste encryption credentials below $keyFile = __DIR__ . '/../../master-key.bin'; if (!file_exists($keyFile)) { file_put_contents($keyFile, random_bytes(96)); } $masterKeyBytes = file_get_contents($keyFile); $kmsProvider = [ 'type' => 'local', 'key' => new Binary( $masterKeyBytes, Binary::TYPE_GENERIC, ), ];
このコードは、96 バイトのローカル CMKファイルを作成またはロードします。$kmsProvider 配列は、暗号化に使用されるローカル KMS プロバイダーを構成します。
警告
ローカル CMK ストレージ
このチュートリアルでは、CMK を ローカルファイルに保存します。本番環境では、このアプローチは使用 しない でください。リモート KMS を使用しないと、暗号化のキーへの不正アクセスや、データの復号に必要なキーが失われるリスクがあります。
自動暗号化オプションを構成します。
前の手順の KMS プロバイダー構成の直下に次のコードを追加します。
$autoEncryptionOptions = [ 'keyVaultNamespace' => $keyVaultNamespace, ]; $cryptSharedLibPath = $_ENV['CRYPT_SHARED_LIB_PATH'] ?? ''; if ($cryptSharedLibPath) { $autoEncryptionOptions['extraOptions'] = [ 'cryptSharedLibPath' => $cryptSharedLibPath, ]; }
このコードでは、キーヴォールトの名前空間を設定し、自動暗号化共有ライブラリへのパスを構成します。
DocumentManager を設定します。
// Paste connection and configuration below コメントの下に次のコードを追加します。
// Paste connection and configuration below $cacheDir = __DIR__ . '/../../var/cache/doctrine'; $config = new Configuration(); $config->setAutoEncryption($autoEncryptionOptions); $config->setKmsProvider($kmsProvider); $config->setProxyDir($cacheDir . '/Proxies'); $config->setProxyNamespace('Proxies'); $config->setHydratorDir($cacheDir . '/Hydrators'); $config->setHydratorNamespace('Hydrators'); $config->setDefaultDB($encryptedDatabase); $config->setMetadataDriverImpl( new AttributeDriver([__DIR__ . '/../Document']) ); $client = new Client( uri: $_ENV['MONGODB_URI'], uriOptions: [], driverOptions: $config->getDriverOptions(), ); $dm = DocumentManager::create($client, $config);
このコードは、暗号化設定を使用して Doctrine Configuration オブジェクトを構成し、暗号化ドライバー オプションを渡す MongoDB クライアントを作成し、暗号化操作用の DocumentManager を初期化します。
暗号化されたコレクションを作成します。
// Paste collection setup below コメントの下に次のコードを追加します。
// Paste collection setup below $schemaManager = $dm->getSchemaManager(); $schemaManager->dropDocumentCollection(Patient::class); $schemaManager->createDocumentCollection(Patient::class);
このコードは、既存のコレクションをすべて削除し、 Queryable Encryptionに必要な暗号化メタデータを持つ新しい patientsコレクションを作成します。createDocumentCollection() を呼び出すたびに、暗号化されたフィールド用に新しいデータ暗号化キーが生成されます。
暗号化された操作の実行
アプリケーションとデータベースの接続を構成したら、このセクションの手順に従って暗号化されたドキュメントの挿入とクエリを行います。
暗号化された データを挿入します。
src/Command/QueryableEncryptionCommand.phpファイルで、// Paste insert operation below コメントの下に次のコードを追加します。
// Paste insert operation below $billing = new Billing(); $billing->type = 'Visa'; $billing->number = '4111111111111111'; $record = new PatientRecord(); $record->ssn = '987-65-4320'; $record->billing = $billing; $record->billAmount = 1500; $patient = new Patient(); $patient->patientName = 'Jon Doe'; $patient->patientId = 12345678; $patient->patientRecord = $record; $dm->persist($patient); $dm->flush(); $dm->clear(); $output->writeln( 'Successfully inserted the patient document.' );
Queryable Encryption は、ドキュメントをMongoDBに保存する前に、patientRecord.ssn フィールドと patientRecord.billing フィールドを自動的に暗号化します。
暗号化された データのクエリ。
// Paste encrypted query below コメントの下に次のコードを追加します。
// Paste encrypted query below $found = $dm ->getRepository(Patient::class) ->findOneBy(['patientRecord.ssn' => '987-65-4320']); if ($found instanceof Patient) { $output->writeln('Found patient:'); $output->writeln( ' Name: ' . $found->patientName ); $output->writeln( ' SSN: ' . $found->patientRecord->ssn ); $output->writeln( ' Billing type: ' . $found->patientRecord->billing->type ); $output->writeln( ' Billing number: ' . $found->patientRecord->billing->number ); $output->writeln( ' Bill amount: ' . $found->patientRecord->billAmount ); } $output->writeln('Connection closed.');
このコードは、暗号化された patientRecord.ssnフィールドに対して等価クエリを実行します。
アプリケーションを実行します。
アプリケーションを起動するには、qe-symfony-appプロジェクトディレクトリから次のコマンドを実行します。
php bin/console app:queryable-encryption
成功した場合、コマンド出力は次の例のようになります。
Successfully inserted the patient document. Found patient: Name: Jon Doe SSN: 987-65-4320 Billing type: Visa Billing number: 4111111111111111 Bill amount: 1500 Connection closed.
データベースでは、ドキュメントは暗号化されています。MongoDB は、#[ODM\Encrypt] 属性でマークされたフィールドをBSONバイナリ データとして保存し、メタデータタグの __safeContent__フィールドを含めます。保存されたドキュメントは、次のようになります。
{ "_id": { "$oid": "..." }, "patientName": "Jon Doe", "patientId": 12345678, "patientRecord": { "ssn": { "$binary": { ... } }, "billing": { "$binary": { ... } }, "billAmount": 1500 }, "__safeContent__": [ { "$binary": { ... } } ] }
次のステップ
Dotene ODM Queryable Encryption のチュートリアルが完了しました。これで、 Queryable Encryptionを使用してドキュメントフィールドを自動的に暗号化および復号化するサンプルSyncorアプリケーションができました。アプリケーションはサーバー側で機密データを暗号化し、クライアント側でデータをクエリします。
Queryable Encryptionと Dotene MongoDB ODM の詳細については、次のリソースを参照してください。
MongoDB Serverマニュアルで、ドライバーQueryable Encryption のチュートリアルをさらに見る
Dotene MongoDB ODM の詳細については、 Dotene MongoDB ODM ドキュメント を参照してください。
Doctrine MongoDB ODM を Symfony と統合する方法の詳細については、Symfony MongoDB 統合チュートリアルを参照してください。