暗号化キー管理
項目一覧
このガイドでは、クライアント側フィールドレベル暗号化(CSFLE)対応アプリケーションでキー管理システム( KMS )を使用して暗号化のキーを管理する方法を学習できます。
暗号化コンポーネント
MongoDB は、次のコンポーネントを使用してクライアント側のフィールドレベル暗号化を実行します。
データ暗号化キー( DEK )s
カスタマー マスター キー( CMK )
キーヴォールト コレクション
キー管理システム( KMS )
キーとキー ボールトの詳細については、「キーとキー ボールト 」を参照してください。
サポートされているキー管理サービス
クライアント側のフィールドレベル暗号化は、次のキー管理システム プロバイダーをサポートします。
Amazon Web Services KMS
Azure Key Vault
Google Cloud KMS
任意の KMIP 準拠キー管理システム
ローカル キー プロバイダー(テスト専用)
デフォルトの KMIP プロトコル バージョンは 1.2 です。MongoDB サーバーの構成ファイルで、KMIP バージョン 1.0 または 1.1 を使用するように MongoDB を構成できます。
アプリケーションがこれらのプロバイダーを使用してクライアント側のフィールドレベル暗号化を実行する方法を示す図を含め、これらのプロバイダーの詳細については、「 CSFLE KMS プロバイダー 」を参照してください。
リモート キー管理システムを使用する理由
リモート キー管理システムを使用してカスタマー マスター キーを管理する方法には、ローカル ファイルシステムを使用してCMKをホストする場合よりも次の利点があります。
アクセス監査を使用してキーを安全にストレージ
アクセス権限の問題のリスク軽減
リモート クライアントへのキーの可用性と配布
キーのバックアップと復元の自動化
一元化された暗号化キーのライフサイクル管理
さらに、次のKMSプロバイダーの場合、 KMSはデータ暗号化キーをリモートで暗号化および復号化し、カスタマー マスター キーが CSFLE 対応アプリケーションに公開されないようにします。
Amazon Web Services KMS
Azure Key Vault
Google Cloud KMS
データ暗号化キーの別名を管理する
データ暗号化キーに代替名を割り当てて、キーを参照しやすくすることができます。 別名を割り当てると、次のアクションを実行できるようになります。
_id
フィールドとは異なる手段でDEKを参照します。実行時に DEK を動的に割り当てます。
別名を使用したデータ暗号化キーの作成
重要
前提条件
新しいキーの代替名を追加する前に、 keyAltNames
フィールドに部分的な一意のインデックスを作成する必要があります。 このインデックスには、 keyAltNames
が存在するドキュメントに対してpartialFilterExpression
が必要です。
クライアント側のフィールドレベル暗号化は、サーバーによって強制されるキーの別名の一意性に依存します。
部分インデックスの作成方法については、「 部分インデックス 」を参照してください。
次の例では、別名を持つデータ暗号化キーを作成します。 ドライバー言語に対応するタブを選択します。
var autoEncryptionOpts = { keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, }; var encryptedClient = Mongo( connectionString, autoEncryptionOpts ); var clientEncryption = encryptedClient.getClientEncryption(); var masterKey = { "<Your dataKeyOpts Key>": "<Your dataKeyOpts Value>", }; var keyVault = encryptedClient.getKeyVault(); var keyId = keyVault.createKey("aws", masterKey, ["<Your Key Alt Name>"]);
var keyVaultClient = new MongoClient(connectionString); var clientEncryptionOptions = new ClientEncryptionOptions( keyVaultClient: keyVaultClient, keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders); var clientEncryption = new ClientEncryption(clientEncryptionOptions); var dataKeyOptions = new DataKeyOptions( alternateKeyNames: new[] { "<Your Key Alt Name>" }, masterKey: new BsonDocument { { "<Your dataKeyOpts Keys>", "<Your dataKeyOpts Values>" }, }); var dataKeyId = clientEncryption.CreateDataKey("<Your KMS Provider>", dataKeyOptions, CancellationToken.None);
clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(KeyVaultNamespace).SetKmsProviders(kmsProviders) keyVaultClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(URI)) if err != nil { return fmt.Errorf("Client connect error %v", err) } clientEnc, err := mongo.NewClientEncryption(keyVaultClient, clientEncryptionOpts) if err != nil { return fmt.Errorf("NewClientEncryption error %v", err) } defer func() { _ = clientEnc.Close(context.TODO()) }() masterKey := map[string]interface{}{ "<Your dataKeyOpts Key>": "<Your dataKeyOpts Value>", } dataKeyOpts := options.DataKey(). SetMasterKey(masterKey). SetKeyAltNames([]string{"<Your Key Alt Name>"}) dataKeyID, err := clientEnc.CreateDataKey(context.TODO(), provider, dataKeyOpts) if err != nil { return fmt.Errorf("create data key error %v", err) }
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString(connectionString)) .build()) .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); BsonDocument masterKeyProperties = new BsonDocument(); masterKeyProperties.put("provider", new BsonString("<Your KMS Provider>")); masterKeyProperties.put("<Your dataKeyOpts Key>", new BsonString("<Your dataKeyOpts Value>")); List keyAltNames = new ArrayList<String>(); keyAltNames.add("<Your Key Alt Name>"); BsonBinary dataKeyId = clientEncryption.createDataKey(kmsProvider, new DataKeyOptions().masterKey(masterKeyProperties).keyAltNames(keyAltNames));
const encryption = new ClientEncryption(client, { keyVaultNamespace, kmsProviders, }); const masterKey = { "<Your dataKeyOpts Key>": "<Your dataKeyOpts Value>", }; const key = await encryption.createDataKey(provider, { masterKey: masterKey, keyAltNames: ["<Your Key Alt Name>"], });
client = MongoClient(connection_string) client_encryption = ClientEncryption( kms_providers, key_vault_namespace, client, CodecOptions(uuid_representation=STANDARD), ) master_key={ "<Your dataKeyOpts Key>" : "<Your dataKeyOpts Value>"} data_key_id = client_encryption.create_data_key(provider, master_key, key_alt_names=["<Your Key Alt Name>"])
dataKeyOpts
オブジェクトとkmsProviders
オブジェクトの詳細については、 CSFLE KMS プロバイダー を参照してください。
自動暗号化スキーマでのキー代替名の使用
暗号化スキーマには、どのフィールドを暗号化する必要があるか、またそれらのフィールドを暗号化する方法を識別するユーザー指定のルールが含まれています。 暗号化ルールでは、フィールドを暗号化するデータ暗号化キーの代替キー名を指定できます。
JSON ポインターを使用してキーの代替名を参照する必要があります。 JSON ポインターは、同じまたは別のドキュメント内の特定のフィールド値にアクセスするために使用できる"/"
文字がプレフィックスが付いた string です。 JSON ポインターを使用して、キーの別名の値を含むクエリまたはアップデートのドキュメント内のフィールドを参照します。
重要
確定的に暗号化されたフィールドに代替名は使用できません
決定的な暗号化アルゴリズム でフィールドを暗号化する場合、 DEK を別名で参照することはできません。フィールドを確定的に暗号化するには、フィールドの暗号化に使用するキーの_id
を指定する必要があります。
暗号化スキーマでの参照キーの代替名
salary
フィールドを暗号化する次の暗号化スキーマを検討します。
{ "<database>.<collection>": { "bsonType": "object", "properties": { "salary": { "encrypt": { "bsonType": "int", "keyId": "/fieldWithAltName", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } } } }
スキーマのkeyId
フィールドには、暗号化されるドキュメント内のfieldWithAltName
フィールドを参照するための JSON ポインターが含まれています。
次のドキュメントのfieldWithAltName
値はmy-alt-name
です。
{ "name": "Jon Doe", "salary": 45000, "fieldWithAltName": "my-alt-name" }
salary
フィールドは、代替名my-alt-name
を持つDEKによって暗号化されます。
実行時にキーを動的に割り当てる
実行時にフィールドの データ暗号化キー を動的に設定するには、代替キー名を使用します。 この機能を使用して、同じ暗号化スキーマを使用して異なる DEK を持つ個々のドキュメントを暗号化します。
例えば、次のドキュメントについて考えてみます。
{ "name": "Jon Doe", "salary": 45000, "fieldWithAltName": "my-alt-name" }, { "name": "Jane Smith", "salary": 70000, "fieldWithAltName": "my-other-alt-name" }
の前の例の暗号化スキーマで構成された CSFLE 対応のクライアントを使用して、上記のドキュメントを挿入します。
暗号化スキーマでは、 salary.encrypt.keyId
フィールドには挿入されたドキュメントのfieldWithAltName
フィールドへの JSON ポインターが含まれます。 その結果、2 つのサンプル ドキュメントのsalary
フィールドはそれぞれ、個々のドキュメントに固有のDEKを使用して暗号化されます。 キーは実行時に動的に割り当てられます。
手順: mongo shellを使用して暗号化キーをローテーションする
mongo shellのバージョン 1.5 以降では、 rewrapManyDataKey
メソッドを使用して暗号化キーをローテーションできます。 rewrapManyDataKey
メソッドは複数のデータキーを自動的に復号化し、指定された CMK を使用して再暗号化します。 次に、キーヴォールトコレクション内のローテーションされたキーをアップデートします。 この方法では、2 つのオプションの引数に基づいて暗号化のキーをローテーションできます。
ローテーションするキーを指定するために使用されるフィルター。 指定されたフィルターに一致するデータキーがない場合、キーはローテーションされません。 フィルターを省略すると、キーヴォールト コレクション内のすべてのキーがローテーションされます。
新しいCMKを表すオブジェクト。 現在の CMK を使用してデータキーをローテーションするには、このオブジェクトを省略します。
rewrapManyDataKey
は次の構文を使用します。
keyVault = db.getKeyVault() keyVault.rewrapManyDataKey( { "<Your custom filter>" }, { provider: "<KMS provider>", masterKey: { "<dataKeyOpts Key>" : "<dataKeyOpts Value>" } } )
KMS プロバイダーのdataKeyOpts
オブジェクトの詳細については、サポートされているキー管理サービス を参照してください。
データ暗号化キーの削除
標準の CRUD削除操作を使用して、Key Vault コレクションからデータ暗号化キーを削除できます。 DEKを削除すると、そのDEKで暗号化されたすべてのフィールドが永続的に読み取りできなくなります。
Tip
MongoDB Shell 固有の機能
MongoDB shell では、次のようにkeyVault.deleteKey()
メソッドを使用してUUID
によってDEKを削除できます。
keyVault = db.getKeyVault() keyVault.deleteKey(UUID("<UUID String>"))
キー Vault コレクションの詳細については、「キー Vault コレクション 」を参照してください。
詳細
サポートされているKMSプロバイダーのそれぞれを使用して、CSFLE 対応のアプリケーションを設定する方法の詳細なチュートリアルについては、次のページを参照してください。
暗号化スキーマのその他の例については、「 CSFLE の暗号化スキーマ 」を参照してください。