암호화 키 관리(Encryption Key Management)
이 페이지의 내용
이 가이드에서는 CSFLE(클라이언트 사이드 필드 레벨 암호화 )가 활성화된 애플리케이션에서 KMS(키 관리 시스템)로 암호화 키를 관리하는 방법을 알아볼 수 있습니다.
암호화 구성 요소
MongoDB는 다음 구성 요소를 사용하여 클라이언트 측 필드 레벨 암호화를 수행합니다.
데이터 암호화 키(DEK)
고객 마스터 키(CMK)
키 볼트 컬렉션
키 관리 시스템(KMS)
키 및 키 볼트에 학습 보려면 암호화 키 및 키 볼트를 참조하세요.
지원되는 키 관리 서비스
클라이언트측 필드 레벨 암호화는 다음 키 관리 시스템 제공자를 지원합니다.
Amazon Web Services KMS
Azure Key Vault
Google Cloud KMS
KMIP를 준수하는 모든 키 관리 시스템
로컬 키 제공자(테스트 전용)
기본 KMIP 프로토콜 버전은 1.2입니다. MongoDB 서버 구성 파일에서 KMIP 버전 1.0 또는 1.1을 사용하도록 MongoDB를 구성할 수 있습니다
애플리케이션 에서 제공자를 사용하여 클라이언트 측 필드 레벨 암호화 를 수행하는 방법을 보여주는 다이어그램을 포함하여 이러한 제공자에 학습 보려면 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
객체에 학습 보려면 KMS 제공자를 참조하세요.
자동 암호화 스키마에서 키 대체 이름 사용
암호화 스키마에는 암호화해야 하는 필드와 해당 필드를 암호화하는 방법을 식별하는 사용자 지정 규칙이 포함되어 있습니다. 암호화 규칙에서 필드를 암호화하는 데이터 암호화 키에 대해한 대체 키 이름을 지정할 수 있습니다.
JSON 포인터를 사용하여 키 대체 이름을 참조해야 합니다. JSON 포인터는 "/"
문자가 접두사로 붙은 문자열로, 같은 문서 또는 다른 문서의 특정 필드 값에 액세스하는 데 사용할 수 있습니다. JSON 포인터를 사용하여 쿼리의 필드를 참조하거나 키 대체 이름의 값이 포함된 문서를 업데이트합니다.
중요
결정론적으로 암호화된 필드에는 대체 이름을 사용할 수 없음
결정론적 암호화 알고리즘으로 필드를 암호화할 때는 DEK의 대체 이름으로 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 포인터가 포함되어 있습니다. 결과적으로 두 예시 문서의 salary
필드는 각각 개별 문서에 특정한 DEK를 사용하여 암호화됩니다. 키는 런타임에 동적으로 할당됩니다.
절차: Mongo 셸을 사용하여 암호화 키 순환
Mongo 셸 버전 1.5 이상에서는 rewrapManyDataKey
메서드를 사용하여 암호화 키를 순환시킬 수 있습니다. rewrapManyDataKey
메서드는 여러 데이터 키를 자동으로 해독하고 지정된 고객 마스터 키를 사용하여 다시 암호화합니다. 그런 다음 키 볼트 컬렉션에서 순환된 키를 업데이트합니다. 이 메서드를 사용하면 두 개의 선택적 인수를 기반으로 암호화 키를 순환시킬 수 있습니다.
순환할 키를 지정하는 데 사용되는 필터입니다. 지정된 필터와 일치하는 데이터 키가 없으면 키가 순환되지 않습니다. 키 볼트 컬렉션의 모든 키를 순환시키려면 필터를 생략합니다.
새 고객 마스터 키(CMK)를 나타내는 객체입니다. 현재 CMK를 사용하여 데이터 키를 회전하려면 이 객체를 생략합니다.
rewrapManyDataKey
는 다음 구문을 사용합니다.
keyVault = db.getKeyVault() keyVault.rewrapManyDataKey( { "<Your custom filter>" }, { provider: "<KMS provider>", masterKey: { "<dataKeyOpts Key>" : "<dataKeyOpts Value>" } } )
KMS 제공자에 대한 dataKeyOpts
객체에 대해 자세히 알아보려면 지원되는 키 관리 서비스를 확인하세요.
데이터 암호화 키 삭제
표준 CRUD 삭제 작업을 사용하여 키 볼트 컬렉션에서 데이터 암호화 키를 삭제할 수 있습니다. DEK를 삭제하면 해당 DEK로 암호화된 모든 필드를 영구적으로 읽을 수 없게 됩니다.
팁
MongoDB Shell별 기능
MongoDB Shell에서는 다음과 같이 keyVault.deleteKey()
메서드를 사용하여 UUID
로 DEK를 삭제할 수 있습니다.
keyVault = db.getKeyVault() keyVault.deleteKey(UUID("<UUID String>"))
키 볼트 컬렉션에 학습 보려면 암호화 키 및 키 볼트를 참조하세요.
자세히 알아보기
지원되는 각 KMS 제공자에서 CSFLE 허용 애플리케이션을 설정하는 방법을 자세히 설명하는 튜토리얼은 다음 페이지를 참조하세요.
암호화 스키마의 추가 예를 보려면 CSFLE 암호화 스키마를 참조하세요.