暗号化 (CSFLE)

クライアント側暗号化は、アプリケーション内のデータを MongoDB に送信する前に暗号化する機能です。Spring Data による暗号化の適用を続行する前に、理想的には MongoDB ドキュメント (英語) から概念を理解し、その機能と制限について詳しく学ぶことをお勧めします。

クライアント側の暗号化を使用するようにドライバー com.mongodb.AutoEncryptionSettings を設定してください。MongoDB は、すべてのフィールド型の暗号化をサポートしているわけではありません。特定のデータ型では、等価比較機能を保持するために決定論的な暗号化が必要です。

自動暗号化

MongoDB は、自動暗号化機能を備えた MongoDB ドライバーを使用して、すぐに使えるクライアント側のフィールドレベル暗号化 (英語) をサポートします。自動暗号化には、明示的な暗号化 / 復号化の手順を行わなくても、暗号化された読み取りおよび書き込み操作を実行できる JSON スキーマが必要です。

暗号化情報を保持する JSON スキーマの定義の詳細については、JSON スキーマセクションを参照してください。

MongoJsonSchema を利用するには、AutoEncryptionSettings と組み合わせる必要があります。MongoClientSettingsBuilderCustomizer 経由。

@Bean
MongoClientSettingsBuilderCustomizer customizer(MappingContext mappingContext) {
    return (builder) -> {

        // ... keyVaultCollection, kmsProvider, ...

        MongoJsonSchemaCreator schemaCreator = MongoJsonSchemaCreator.create(mappingContext);
        MongoJsonSchema patientSchema = schemaCreator
            .filter(MongoJsonSchemaCreator.encryptedOnly())
            .createSchemaFor(Patient.class);

        AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder()
            .keyVaultNamespace(keyVaultCollection)
            .kmsProviders(kmsProviders)
            .extraOptions(extraOpts)
            .schemaMap(Collections.singletonMap("db.patient", patientSchema.schemaDocument().toBsonDocument()))
            .build();

        builder.autoEncryptionSettings(autoEncryptionSettings);
    };
}

明示的な暗号化

明示的な暗号化では、MongoDB ドライバーの暗号化ライブラリ (org.mongodb:mongodb-crypt) を使用して暗号化タスクと復号化タスクを実行します。@ExplicitEncrypted アノテーションは、JSON スキーマの作成プロパティコンバーターに使用される @Encrypted アノテーションを組み合わせたものです。言い換えれば、@ExplicitEncrypted は既存のビルドブロックを使用して結合し、簡略化された明示的な暗号化サポートを実現します。

@ExplicitEncrypted のアノテーションが付けられたフィールドは、常に全体として暗号化されます。次の例を考えてみましょう。

@ExplicitEncrypted(…)
String simpleValue;        (1)

@ExplicitEncrypted(…)
Address address;           (2)

@ExplicitEncrypted(…)
List<...> list;            (3)

@ExplicitEncrypted(…)
Map<..., ...> mapOfString; (4)
1null でない場合は String などの単純型の値を暗号化します。
2Address オブジェクト全体とそのすべてのネストされたフィールドを Document として暗号化します。Address#street など、Address の一部のみを暗号化するには、Address 内の street フィールドに @ExplicitEncrypted のアノテーションを付ける必要があります。
3Collection - 同様のフィールドは、エントリごとではなく単一の値として暗号化されます。
4Map -like フィールドは、キー / 値エントリとしてではなく、単一の値として暗号化されます。

クライアント側のフィールドレベル暗号化を使用すると、決定的アルゴリズムとランダム化アルゴリズムのどちらかを選択できます。選択したアルゴリズム (英語) に応じて、異なる操作 (英語) がサポートされる場合があります。特定のアルゴリズムを選択するには、@ExplicitEncrypted(algorithm) を使用します。アルゴリズム定数については、EncryptionAlgorithms を参照してください。アルゴリズムとその使用箇所の詳細については、暗号化の種類 (英語) マニュアルを参照してください。

実際の暗号化を実行するには、データ暗号化キー (DEK) が必要です。キー管理の設定方法とデータ暗号化キーの作成方法の詳細については、MongoDB ドキュメント (英語) を参照してください。DEK は、id または定義された別名を介して直接参照できます。@EncryptedField アノテーションでは、代替名による DEK の参照のみが許可されます。後述する EncryptionKeyResolver を任意の DEK に提供することが可能です。

例 1: データ暗号化キーの参照
@EncryptedField(algorithm=…, altKeyName = "secret-key") (1)
String ssn;
@EncryptedField(algorithm=…, altKeyName = "/name")      (2)
String ssn;
1 代替名 secret-key で保存された DEK を使用します。
2 実際のフィールド値を読み取り、それをキー検索に使用するフィールド参照を使用します。保存操作には常に完全なドキュメントが存在する必要があります。フィールドはクエリ / 集計では使用できません。

デフォルトでは、@ExplicitEncrypted(value= …) 属性は MongoEncryptionConverter を参照します。対応する型参照を提供することで、デフォルトの実装を変更し、任意の PropertyValueConverter 実装と交換することができます。カスタム PropertyValueConverters と必要な構成の詳細については、"プロパティコンバーター - 特定のフィールドのマッピング" セクションを参照してください。

MongoEncryptionConverter セットアップ

MongoEncryptionConverter のコンバーターのセットアップには、いくつかのコンポーネントが関係するため、いくつかの手順が必要です。Bean セットアップは以下で構成されます。

  1. ClientEncryption エンジン

  2. ClientEncryption および EncryptionKeyResolver で構成された MongoEncryptionConverter インスタンス。

  3. 登録された MongoEncryptionConverter Bean を使用する PropertyValueConverterFactory

アノテーション付きキー解決を使用する副作用は、@ExplicitEncrypted アノテーションで alt キー名を指定する必要がないことです。EncryptionKeyResolver は、動的な DEK 解決を可能にするプロパティへのアクセスを提供する EncryptionContext を使用します。

例 2: MongoEncryptionConverter 構成のサンプル
class Config extends AbstractMongoClientConfiguration {

    @Autowired ApplicationContext appContext;

    @Bean
    ClientEncryption clientEncryption() {                                                            (1)
        ClientEncryptionSettings encryptionSettings = ClientEncryptionSettings.builder();
        // …

        return ClientEncryptions.create(encryptionSettings);
    }

    @Bean
    MongoEncryptionConverter encryptingConverter(ClientEncryption clientEncryption) {

        Encryption<BsonValue, BsonBinary> encryption = MongoClientEncryption.just(clientEncryption);
        EncryptionKeyResolver keyResolver = EncryptionKeyResolver.annotated((ctx) -> …);             (2)

        return new MongoEncryptionConverter(encryption, keyResolver);                                (3)
    }

    @Override
    protected void configureConverters(MongoConverterConfigurationAdapter adapter) {

        adapter
            .registerPropertyValueConverterFactory(PropertyValueConverterFactory.beanFactoryAware(appContext)); (4)
    }
}
1com.mongodb.client.vault.ClientEncryption を使用して Encryption エンジンをセットアップします。インスタンスはステートフルであるため、使用後は閉じる必要があります。ClientEncryption は Closeable であるため、Spring がこれを処理します。
2 アノテーションから EncryptionKey を決定するには、アノテーションベースの EncryptionKeyResolver をセットアップします。
3MongoEncryptionConverter を作成します。
4BeanFactory からの PropertyValueConverter ルックアップを有効にします。