client-side-field-level-encryption"> client-side-field-level-encryption"> MongoDB との統合 クライアントサイド フィールドレベル暗号化

クライアント側フィールドレベル暗号化、略して CSFLE とは、MongoDB でデータを暗号化された形式で格納するためのツールです。たとえば、`name` プロパティをプレーンテキスト文字列として格納する代わりに、CSFLE を使用すると MongoDB は `name` を暗号化バッファー付きドキュメントとして格納します。結果のドキュメントは、データを復号化するアクセス権を持たないクライアントからみると次のようになります。

{
  "_id" : ObjectId("647a3207661e3a3a1bc3e614"),
  "name" : BinData(6,"ASrIv7XfokKwiCUJEjckOdgCG+u6IqavcOWX8hINz29MLvcKDZ4nnjCnPFZG+0ftVxMdWgzu6Vdh7ys1uIK1WiaPN0SqpmmtL2rPoqT9gfhADpGDmI60+vm0bJepXNY1Gv0="),
  "__v" : 0
}

CSFLE について詳しくは、MongoDB CSFLE ドキュメントNode.js の CSFLE に関するブログ記事 を参照してください。

現在、Mongoose には CSFLE 専用の Mongoose 特有 API がありません。Mongoose は CSFLE 関連の作業をすべて MongoDB Node.js ドライバーに委任するため、CSFLE 関連の設定は `mongoose.connect()` と `mongoose.createConnection()` の autoEncryption オプション に配置されます。Mongoose スキーマは現在、CSFLE 設定をサポートしていません。

Mongoose でフィールドレベル暗号化をセットアップする

まず、mongodb-client-encryption npm パッケージをインストールする必要があります。これは、暗号化キーをセットアップするための MongoDB の公式パッケージです。

npm install mongodb-client-encryption

また、mongocryptd がインストールされていることを確認する必要があります。mongocryptd は、フィールドレベル暗号化で動作するために実行する必要がある MongoDB サーバーとは別のプロセスです。mongocryptd を自分で実行するか、システムのパスにあり、MongoDB Node.js ドライバーが代わりに実行できるようにします。 mongocryptd の詳細をこちらで読むことができます

mongocryptd のセットアップと実行が完了したら、まず次のように新しい暗号化キーを作成する必要があります。以下の例は、作業を始めるのに役立つ簡単な例です。以下の例の暗号化キーは安全ではありません。MongoDB では KMS の使用を推奨します。

const { ClientEncryption } = require('mongodb-client-encryption');
const mongoose = require('mongoose');
const { Binary } = require('mongodb');

run().catch(err => console.log(err));

async function run() {
  /* Step 1: Connect to MongoDB and insert a key */

  // Create a very basic key. You're responsible for making
  // your key secure, don't use this in prod :)
  const arr = [];
  for (let i = 0; i < 96; ++i) {
    arr.push(i);
  }
  const key = Buffer.from(arr);

  const keyVaultNamespace = 'client.encryption';
  const kmsProviders = { local: { key } };

  const uri = 'mongodb://127.0.0.1:27017/mongoose_test';
  const conn = await mongoose.createConnection(uri, {
    autoEncryption: {
      keyVaultNamespace,
      kmsProviders
    }
  }).asPromise();
  const encryption = new ClientEncryption(conn.client, {
    keyVaultNamespace,
    kmsProviders,
  });

  const _key = await encryption.createDataKey('local');
}

暗号化キーを取得したら、以下のように JSON スキーマ構文を使用して、どのフィールドが暗号化されるかを定義する schemaMap を使用して、別の Mongoose 接続を作成できます。

/* Step 2: connect using schema map and new key */
await mongoose.connect('mongodb://127.0.0.1:27017/mongoose_test', {
  // Configure auto encryption
  autoEncryption: {
    keyVaultNamespace,
    kmsProviders,
    schemaMap: {
      'mongoose_test.tests': {
        bsonType: 'object',
        encryptMetadata: {
          keyId: [_key]
        },
        properties: {
          name: {
            encrypt: {
              bsonType: 'string',
              algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
            }
          }
        }
      }
    }
  }
});

上記の接続では、「テスト」コレクションを使用する「Test」というモデルを作成すると、ドキュメントの `name` プロパティがすべて暗号化されます。

// 'super secret' will be stored as 'BinData' in the database,
// if you query using the `mongo` shell.
const Model = mongoose.model('Test', mongoose.Schema({ name: String }));
await Model.create({ name: 'super secret' });