Docs Menu
Docs Home
/
MongoDB マニュアル
/ / / / /

暗号化キー管理

項目一覧

  • 暗号化コンポーネント
  • サポートされているキー管理サービス
  • リモート キー管理システムを使用する理由
  • データ暗号化キーの別名を管理する
  • 別名を使用したデータ暗号化キーの作成
  • 自動暗号化スキーマでのキー代替名の使用
  • 手順: mongo shellを使用して暗号化キーをローテーションする
  • データ暗号化キーの削除
  • 詳細

このガイドでは、クライアント側フィールドレベル暗号化(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フィールドに一意のインデックスを作成する必要があります。 クライアント側のフィールドレベル暗号化は、キー代替名がサーバーによって強制される一意であるかどうかに依存します。

一意のインデックスの作成方法については、「一意なインデックス 」を参照してください。

次の例では、別名を持つデータ暗号化キーを作成します。 ドライバー言語に対応するタブを選択します。

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のバージョン 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 の暗号化スキーマ 」を参照してください。

戻る

キーとキー ボールト