문서 메뉴
문서 홈
/
MongoDB 매뉴얼
/ / / / /

AWS에서 자동 클라이언트 측 필드 수준 암호화 사용

이 페이지의 내용

  • 개요
  • 시작하기 전에
  • KMS 설정
  • 고객 마스터 키 생성
  • AWS IAM 사용자 생성
  • 애플리케이션 생성
  • 키 볼트 collection에 고유 인덱스 만들기
  • 새 데이터 암호화 키 생성
  • MongoClient 구성
  • 암호화된 필드가 있는 문서 삽입하기
  • 암호화된 문서 조회
  • 자세히 알아보기

이 안내서는 Amazon Web Services(AWS) KMS를 사용하여 클라이언트 측 필드 레벨 암호화(CSFLE) 지원 애플리케이션을 구축하는 방법을 보여줍니다.

이 가이드의 단계를 완료하면 다음과 같은 내용이 표시됩니다:

  • AWS KMS 인스턴스에서 호스팅되는 고객 마스터 키입니다.

  • 고객 마스터 키를 사용하여 암호화된 문서를 삽입하는 작동하는 클라이언트 애플리케이션입니다.

이 가이드의 코드를 완료하고 실행하려면 설치 요구 사항 페이지에 표시된 대로 개발 환경을 설정해야 합니다.

이 가이드 전체에서 코드 예제에는 placeholder 텍스트가 사용됩니다. 예제를 실행하기 전에 placeholder를 자신의 값으로 대체합니다.

예를 들면 다음과 같습니다.

dek_id := "<Your Base64 DEK ID>"

따옴표 사이의 모든 내용을 DEK ID로 바꿉니다.

dek_id := "abc123"

페이지 오른쪽의 Select your language 드롭다운 메뉴에서 코드 예제를 보려는 프로그래밍 언어를 선택합니다.

참조: 전체 적용

이 튜토리얼의 실행 가능한 전체 애플리케이션 코드를 보려면 다음 링크로 이동하십시오.

C# 애플리케이션 완성

// You are viewing the C# driver code examples.
// Use the dropdown menu to select a different driver.
// You are viewing the Golang driver code examples.
// Use the dropdown menu to select a different driver.
// You are viewing the Java synchronous driver code examples.
// Use the dropdown menu to select a different driver.
// You are viewing the Node.js driver code examples.
// Use the dropdown menu to select a different driver.
# You are viewing the Python driver code examples.
# Use the dropdown menu to select a different driver.
1
1
2
3

대칭 KMS 키 생성 에 대한 AWS 공식 설명서에 따라 새 대칭 키를 생성합니다. . 생성한 키는 고객 마스터 키입니다. 식별에 도움이 되는 이름과 설명을 선택합니다. 이러한 필드는 CMK 의 기능이나 구성에 영향을 주지 않습니다.

키 생성 프로세스의 Usage Permissions 단계에서 ID 및 액세스 관리(IAM) 정책을 활성화하여 고객 마스터 키에 대한 액세스 권한을 부여하는 다음 기본 키 정책을 적용합니다.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "<ARN of your AWS account principal>"
},
"Action": "kms:*",
"Resource": "*"
}
]
}

중요

고객 마스터 키의 Amazon 리소스 이름(ARN) 및 지역을 기록합니다. 이 가이드의 뒷부분에서 이를 사용하게 됩니다.

자세히 알아보기

고객 마스터 키에 대해 자세히 알아보려면 Key & Key Vault를 참조하십시오.

키 정책에 대해 자세히 알아보려면 Amazon Web Services 의 키 정책 KMS 을 참조하세요. 공식 Amazon Web Services 설명서에서 확인 가능합니다.

2
1
2

사용자 추가 에 대한 공식 AWS 설명서에 따라 AWS 관리 콘솔에서 새 프로그래밍 IAM 사용자를 생성합니다. . 이 IAM 사용자를 CSFLE 지원 애플리케이션의 서비스 계정으로 사용하게 됩니다. 애플리케이션은 고객 마스터 키(CMK)로 데이터 암호화 키(DEK)를 암호화 및 복호화하기 위해 IAM 사용자를 사용하여 AWS KMS로 인증합니다.

중요

자격 증명 기록

IAM 사용자를 생성하는 마지막 단계에서 다음 IAM 자격 증명을 기록해야 합니다.

  • 액세스 키 ID

  • 시크릿 액세스 키

이러한 자격 증명을 기록할 수 있는 기회가 한 번 있습니다. 이 단계에서 이러한 자격 증명을 기록하지 않으면 다른 IAM 사용자를 만들어야 합니다.

3

IAM 사용자에게 원격 마스터 키에 대한 kms:Encryptkms:Decrypt 권한을 부여합니다.

중요

새 클라이언트 IAM 사용자는 마스터 키에 대한 관리 권한이 없어야 합니다. 데이터를 안전하게 유지하려면 최소 권한 원칙을 따릅니다.

다음 인라인 정책은 IAM 사용자가 가능한 최소 권한으로 고객 마스터 키를 사용하여 암호화하고 해독할 수 있도록 허용합니다.

참고

원격 마스터 키 ARN

다음 정책에는 이 가이드 의 마스터 키 생성 단계에서 생성한 키의 ARN이 필요합니다.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["kms:Decrypt", "kms:Encrypt"],
"Resource": "<the Amazon Resource Name (ARN) of your remote master key>"
}
]
}

이전 정책을 IAM 사용자에게 적용하려면 AWS 설명서의 IAM ID 권한 추가하기 가이드를 따르세요.

중요

프로덕션에서 IAM 역할로 인증하기

CSFLE 지원 애플리케이션을 프로덕션 환경에 배포할 때는 IAM 사용자 대신 IAM 역할을 통해 애플리케이션을 인증합니다.

IAM 역할로 인증하려면 다음과 같이 KMS 제공자 객체에 임시 IAM 역할 자격 증명을 지정합니다.

{
"accessKeyId":"<temporary access key ID>",
"secretAccessKey":"<temporary secret access key>",
"sessionToken":"<temporary session token>"
}

다음 메커니즘을 통해 임시 IAM 역할 자격 증명을 얻을 수 있습니다.

각 임시 자격 증명 세트가 만료될 때 새 임시 자격 증명을 가져오고 CSFLE 지원 MongoClient 인스턴스를 다시 생성하는 로직이 애플리케이션에 포함되어야 합니다.

IAM 역할에 대해 자세히 알아보려면 공식 AWS 설명서의 다음 페이지를 참조하세요.

이 가이드에서 지원되는 각 언어로 임시 자격 증명을 얻고 역할을 맡는 방법을 알아보려면 Amazon Web Services 설명서에서 다음 AssumeRole 실행 가능한 예제를 참조하세요.

1

collection의 필드에 고유 인덱스를 생성합니다.keyAltNames encryption.__keyVault

선호하는 MongoDB 드라이버에 해당하는 탭을 선택합니다:

메이크데이터키.cs
var connectionString = "<Your MongoDB URI>";
var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
var keyVaultClient = new MongoClient(connectionString);
var indexOptions = new CreateIndexOptions<BsonDocument>();
indexOptions.Unique = true;
indexOptions.PartialFilterExpression = new BsonDocument { { "keyAltNames", new BsonDocument { { "$exists", new BsonBoolean(true) } } } };
var builder = Builders<BsonDocument>.IndexKeys;
var indexKeysDocument = builder.Ascending("keyAltNames");
var indexModel = new CreateIndexModel<BsonDocument>(indexKeysDocument, indexOptions);
var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.ToString());
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);
// Drop the database storing your encrypted fields as all
// the DEKs encrypting those fields were deleted in the preceding line.
keyVaultClient.GetDatabase("medicalRecords").DropCollection("patients");
var keyVaultCollection = keyVaultDatabase.GetCollection<BsonDocument>(keyVaultNamespace.CollectionName.ToString());
keyVaultCollection.Indexes.CreateOne(indexModel);
insert-encrypted-document.go
uri := "<Your MongoDB URI>"
keyVaultClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
if err != nil {
return fmt.Errorf("Connect error for regular client: %v", err)
}
defer func() {
_ = keyVaultClient.Disconnect(context.TODO())
}()
keyVaultColl := "__keyVault"
keyVaultDb := "encryption"
keyVaultNamespace := keyVaultDb + "." + keyVaultColl
keyVaultIndex := mongo.IndexModel{
Keys: bson.D{{"keyAltNames", 1}},
Options: options.Index().
SetUnique(true).
SetPartialFilterExpression(bson.D{
{"keyAltNames", bson.D{
{"$exists", true},
}},
}),
}
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
if err = keyVaultClient.Database(keyVaultDb).Collection(keyVaultColl).Drop(context.TODO()); err != nil {
log.Fatalf("Collection.Drop error: %v", err)
}
// Drop the database storing your encrypted fields as all
// the DEKs encrypting those fields were deleted in the preceding line.
if err = keyVaultClient.Database("medicalRecords").Collection("patients").Drop(context.TODO()); err != nil {
log.Fatalf("Collection.Drop error: %v", err)
}
_, err = keyVaultClient.Database(keyVaultDb).Collection(keyVaultColl).Indexes().CreateOne(context.TODO(), keyVaultIndex)
if err != nil {
panic(err)
}
MakeDataKey.java
String connectionString = "<Your MongoDB URI>";
String keyVaultDb = "encryption";
String keyVaultColl = "__keyVault";
String keyVaultNamespace = keyVaultDb + "." + keyVaultColl;
MongoClient keyVaultClient = MongoClients.create(connectionString);
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
keyVaultClient.getDatabase(keyVaultDb).getCollection(keyVaultColl).drop();
// Drop the database storing your encrypted fields as all
// the DEKs encrypting those fields were deleted in the preceding line.
keyVaultClient.getDatabase("medicalRecords").getCollection("patients").drop();
MongoCollection keyVaultCollection = keyVaultClient.getDatabase(keyVaultDb).getCollection(keyVaultColl);
IndexOptions indexOpts = new IndexOptions().partialFilterExpression(new BsonDocument("keyAltNames", new BsonDocument("$exists", new BsonBoolean(true) ))).unique(true);
keyVaultCollection.createIndex(new BsonDocument("keyAltNames", new BsonInt32(1)), indexOpts);
keyVaultClient.close();
create_data_key.js
const uri = "<Your Connection String>";
const keyVaultDatabase = "encryption";
const keyVaultCollection = "__keyVault";
const keyVaultNamespace = `${keyVaultDatabase}.${keyVaultCollection}`;
const keyVaultClient = new MongoClient(uri);
await keyVaultClient.connect();
const keyVaultDB = keyVaultClient.db(keyVaultDatabase);
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
await keyVaultDB.dropDatabase();
// Drop the database storing your encrypted fields as all
// the DEKs encrypting those fields were deleted in the preceding line.
await keyVaultClient.db("medicalRecords").dropDatabase();
const keyVaultColl = keyVaultDB.collection(keyVaultCollection);
await keyVaultColl.createIndex(
{ keyAltNames: 1 },
{
unique: true,
partialFilterExpression: { keyAltNames: { $exists: true } },
}
);
make_data_key.py
connection_string = "<your connection string here>"
key_vault_coll = "__keyVault"
key_vault_db = "encryption"
key_vault_namespace = f"{key_vault_db}.{key_vault_coll}"
key_vault_client = MongoClient(connection_string)
# Drop the Key Vault Collection in case you created this collection
# in a previous run of this application.
key_vault_client.drop_database(key_vault_db)
# Drop the database storing your encrypted fields as all
# the DEKs encrypting those fields were deleted in the preceding line.
key_vault_client["medicalRecords"].drop_collection("patients")
key_vault_client[key_vault_db][key_vault_coll].create_index(
[("keyAltNames", ASCENDING)],
unique=True,
partialFilterExpression={"keyAltNames": {"$exists": True}},
)
2
1

CSFLE 지원 클라이언트 코드에 서비스 계정 자격 증명을 추가합니다.

이 가이드 의 IAM 사용자 생성 단계에서 액세스 키 ID와 비밀 액세스 키를 생성하고 기록했습니다.

메이크데이터키.cs
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
var provider = "aws";
var awsKmsOptions = new Dictionary<string, object>
{
{ "accessKeyId", "<Your AWS Access Key ID>" },
{ "secretAccessKey", "<Your AWS Secret Access Key>" }
};
kmsProviders.Add(provider, awsKmsOptions);
make-data-key.go
provider := "aws"
kmsProviders := map[string]map[string]interface{}{
provider: {
"accessKeyId": "<Your AWS Access Key ID>",
"secretAccessKey": "<Your AWS Secret Access Key>",
},
}
MakeDataKey.java
Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
String kmsProvider = "aws";
Map<String, Object> providerDetails = new HashMap<>();
providerDetails.put("accessKeyId", new BsonString("<IAM User Access Key ID>"));
providerDetails.put("secretAccessKey", new BsonString("<IAM User Secret Access Key>"));
kmsProviders.put(kmsProvider, providerDetails);
create_data_key.js
const provider = "aws";
const kmsProviders = {
aws: {
accessKeyId: "<Your AWS Access Key ID>",
secretAccessKey: "<Your AWS Secret Access Key>",
},
};
make_data_key.py
provider = "aws"
kms_providers = {
provider: {
"accessKeyId": "<IAM User Access Key ID>",
"secretAccessKey": "<IAM User Secret Access Key>",
}
}

자세히 알아보기

AWS용 KMS 제공자 객체에 대해 자세히 알아보려면 Amazon Web Services KMS를 참조하세요.

2

고객 마스터 키를 지정하려면 다음 코드를 업데이트하세요.

이 가이드 의 고객 마스터 키 생성 단계에서 고객 마스터 키의 ARN및 리전을 기록했습니다.

메이크데이터키.cs
var dataKeyOptions = new DataKeyOptions(
masterKey: new BsonDocument
{
{ "region", "<Your AWS Key Region>" },
{ "key", "<Your AWS Key ARN>" },
});
make-data-key.go
masterKey := map[string]interface{}{
"key": "<Your AWS Key ARN>",
"region": "<Your AWS Key Region>",
}
MakeDataKey.java
masterKeyProperties.put("provider", new BsonString(kmsProvider));
masterKeyProperties.put("key", new BsonString("<Master Key ARN>"));
masterKeyProperties.put("region", new BsonString("<Master Key AWS Region>"));
create_data_key.js
const masterKey = {
key: "<Your AWS Key ARN>",
region: "<Your AWS Key Region>",
};
make_data_key.py
master_key = {"region": "<Master Key AWS Region>", "key": "<Master Key ARN>"}
3
메이크데이터키.cs
var clientEncryptionOptions = new ClientEncryptionOptions(
keyVaultClient: keyVaultClient,
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders
);
var clientEncryption = new ClientEncryption(clientEncryptionOptions);
var dataKeyId = clientEncryption.CreateDataKey(provider, dataKeyOptions, CancellationToken.None);
var dataKeyIdBase64 = Convert.ToBase64String(GuidConverter.ToBytes(dataKeyId, GuidRepresentation.Standard));
Console.WriteLine($"DataKeyId [base64]: {dataKeyIdBase64}");
make-data-key.go
clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(keyVaultNamespace).
SetKmsProviders(kmsProviders)
clientEnc, err := mongo.NewClientEncryption(keyVaultClient, clientEncryptionOpts)
if err != nil {
return fmt.Errorf("NewClientEncryption error %v", err)
}
defer func() {
_ = clientEnc.Close(context.TODO())
}()
dataKeyOpts := options.DataKey().
SetMasterKey(masterKey)
dataKeyID, err := clientEnc.CreateDataKey(context.TODO(), provider, dataKeyOpts)
if err != nil {
return fmt.Errorf("create data key error %v", err)
}
fmt.Printf("DataKeyId [base64]: %s\n", base64.StdEncoding.EncodeToString(dataKeyID.Data))
MakeDataKey.java
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.build())
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.build();
MongoClient regularClient = MongoClients.create(connectionString);
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
BsonBinary dataKeyId = clientEncryption.createDataKey(kmsProvider, new DataKeyOptions().masterKey(masterKeyProperties));
String base64DataKeyId = Base64.getEncoder().encodeToString(dataKeyId.getData());
System.out.println("DataKeyId [base64]: " + base64DataKeyId);
clientEncryption.close();
create_data_key.js
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
await client.connect();
const encryption = new ClientEncryption(client, {
keyVaultNamespace,
kmsProviders,
});
const key = await encryption.createDataKey(provider, {
masterKey: masterKey,
});
console.log("DataKeyId [base64]: ", key.toString("base64"));
await keyVaultClient.close();
await client.close();
make_data_key.py
key_vault_database = "encryption"
key_vault_collection = "__keyVault"
key_vault_namespace = f"{key_vault_database}.{key_vault_collection}"
client = MongoClient(connection_string)
client_encryption = ClientEncryption(
kms_providers, # pass in the kms_providers variable from the previous step
key_vault_namespace,
client,
CodecOptions(uuid_representation=STANDARD),
)
data_key_id = client_encryption.create_data_key(provider, master_key)
base_64_data_key_id = base64.b64encode(data_key_id)
print("DataKeyId [base64]: ", base_64_data_key_id)

자세히 알아보기

AWS KMS를 사용할 때 클라이언트 애플리케이션이 데이터 암호화 키를 생성하는 방법을 보여주는 다이어그램을 보려면 아키텍처를 참조하세요.

AWS KMS에서 호스팅되는 고객 마스터 키로 암호화된 데이터 암호화 키를 만드는 옵션에 대해 자세히 알아보려면 dataKeyOpts Object를 참조하세요.

참조: 코드 완성

데이터 암호화 키를 만들기 위한 전체 코드를 보려면 Github 리포지토리 를 참조하세요.

데이터 암호화 키를 만들기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

데이터 암호화 키를 만들기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

데이터 암호화 키를 만들기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

데이터 암호화 키를 만들기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

3
1

키 볼트 collection 네임스페이스로 encryption.__keyVault 을 지정합니다.

InsertEncryptedDocument.cs
var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
insert-encrypted-document.go
keyVaultNamespace := "encryption.__keyVault"
InsertEncryptedDocument.java
String keyVaultNamespace = "encryption.__keyVault";
insert_encrypted_document.js
const keyVaultNamespace = "encryption.__keyVault";
insert_encrypted_document.py
key_vault_namespace = "encryption.__keyVault"
2

aws KMS 공급자와 IAM 사용자 자격 증명을 지정합니다.

이 가이드 의 IAM 사용자 생성 단계에서 액세스 키 ID와 비밀 액세스 키를 생성하고 기록했습니다.

InsertEncryptedDocument.cs
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
var provider = "aws";
var awsKmsOptions = new Dictionary<string, object>
{
{ "accessKeyId", "<Your AWS Access Key ID>" },
{ "secretAccessKey", "<Your AWS Secret Access Key>" }
};
kmsProviders.Add(provider, awsKmsOptions);
insert-encrypted-document.go
kmsProviders := map[string]map[string]interface{}{
"aws": {
"accessKeyId": "<Your AWS Access Key ID>",
"secretAccessKey": "<Your AWS Secret Access Key>",
},
}
InsertEncryptedDocument.java
Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
String kmsProvider = "aws";
Map<String, Object> providerDetails = new HashMap<>();
providerDetails.put("accessKeyId", "<IAM User Access Key ID>");
providerDetails.put("secretAccessKey", "<IAM User Secret Access Key>");
kmsProviders.put(kmsProvider, providerDetails);
insert_encrypted_document.js
const kmsProviders = {
aws: {
accessKeyId: "<Your AWS Access Key ID>",
secretAccessKey: "<Your AWS Secret Access Key>",
},
};
insert_encrypted_document.py
provider = "aws"
kms_providers = {
"aws": {
"accessKeyId": "<IAM User Access Key ID>",
"secretAccessKey": "<IAM User Secret Access Key>",
}
}
3

데이터 암호화 키 Base64 ID 추가하기

기본64 DEK ID를 포함하도록 다음 코드를 업데이트해야 합니다. 이 가이드의 데이터 암호화 키 생성 단계에서 이 값을 받았습니다.

InsertEncryptedDocument.cs
var keyId = "<Your base64 DEK ID here>";
var schema = new BsonDocument
{
{ "bsonType", "object" },
{
"encryptMetadata",
new BsonDocument("keyId", new BsonArray(new[] { new BsonBinaryData(Convert.FromBase64String(keyId), BsonBinarySubType.UuidStandard) }))
},
{
"properties",
new BsonDocument
{
{
"ssn", new BsonDocument
{
{
"encrypt", new BsonDocument
{
{ "bsonType", "int" },
{ "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" }
}
}
}
},
{
"bloodType", new BsonDocument
{
{
"encrypt", new BsonDocument
{
{ "bsonType", "string" },
{ "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random" }
}
}
}
},
{
"medicalRecords", new BsonDocument
{
{
"encrypt", new BsonDocument
{
{ "bsonType", "array" },
{ "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random" }
}
}
}
},
{
"insurance", new BsonDocument
{
{ "bsonType", "object" },
{
"properties", new BsonDocument
{
{
"policyNumber", new BsonDocument
{
{
"encrypt", new BsonDocument
{
{ "bsonType", "int" },
{ "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" }
}
}
}
}
}
}
}
}
}
}
};
var schemaMap = new Dictionary<string, BsonDocument>();
schemaMap.Add(dbNamespace, schema);
insert-encrypted-document.go
dek_id := "<Your Base64 DEK ID>"
schema_template := `{
"bsonType": "object",
"encryptMetadata": {
"keyId": [
{
"$binary": {
"base64": "%s",
"subType": "04"
}
}
]
},
"properties": {
"insurance": {
"bsonType": "object",
"properties": {
"policyNumber": {
"encrypt": {
"bsonType": "int",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
}
}
}
},
"medicalRecords": {
"encrypt": {
"bsonType": "array",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
}
},
"bloodType": {
"encrypt": {
"bsonType": "string",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
}
},
"ssn": {
"encrypt": {
"bsonType": "int",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
}
}
}
}`
schema := fmt.Sprintf(schema_template, dek_id)
var schemaDoc bson.Raw
if err := bson.UnmarshalExtJSON([]byte(schema), true, &schemaDoc); err != nil {
return fmt.Errorf("UnmarshalExtJSON error: %v", err)
}
schemaMap := map[string]interface{}{
dbName + "." + collName: schemaDoc,
}
InsertEncryptedDocument.java
String dekId = "<paste-base-64-encoded-data-encryption-key-id>>";
Document jsonSchema = new Document().append("bsonType", "object").append("encryptMetadata",
new Document().append("keyId", new ArrayList<>((Arrays.asList(new Document().append("$binary", new Document()
.append("base64", dekId)
.append("subType", "04")))))))
.append("properties", new Document()
.append("ssn", new Document().append("encrypt", new Document()
.append("bsonType", "int")
.append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic")))
.append("bloodType", new Document().append("encrypt", new Document()
.append("bsonType", "string")
.append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random")))
.append("medicalRecords", new Document().append("encrypt", new Document()
.append("bsonType", "array")
.append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random")))
.append("insurance", new Document()
.append("bsonType", "object")
.append("properties",
new Document().append("policyNumber", new Document().append("encrypt", new Document()
.append("bsonType", "int")
.append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"))))));
HashMap<String, BsonDocument> schemaMap = new HashMap<String, BsonDocument>();
schemaMap.put("medicalRecords.patients", BsonDocument.parse(jsonSchema.toJson()));
insert_encrypted_document.js
dataKey = "<Your base64 DEK ID>";
const schema = {
bsonType: "object",
encryptMetadata: {
keyId: [new Binary(Buffer.from(dataKey, "base64"), 4)],
},
properties: {
insurance: {
bsonType: "object",
properties: {
policyNumber: {
encrypt: {
bsonType: "int",
algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
},
},
},
},
medicalRecords: {
encrypt: {
bsonType: "array",
algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random",
},
},
bloodType: {
encrypt: {
bsonType: "string",
algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random",
},
},
ssn: {
encrypt: {
bsonType: "int",
algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
},
},
},
};
var patientSchema = {};
patientSchema[namespace] = schema;
insert_encrypted_document.py
dek_id = b"<paste-base-64-encoded-data-encryption-key-id>"
json_schema = {
"bsonType": "object",
"encryptMetadata": {"keyId": [Binary(base64.b64decode(dek_id), UUID_SUBTYPE)]},
"properties": {
"insurance": {
"bsonType": "object",
"properties": {
"policyNumber": {
"encrypt": {
"bsonType": "int",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
}
}
},
},
"medicalRecords": {
"encrypt": {
"bsonType": "array",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random",
}
},
"bloodType": {
"encrypt": {
"bsonType": "string",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random",
}
},
"ssn": {
"encrypt": {
"bsonType": "int",
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
}
},
},
}
patient_schema = {"medicalRecords.patients": json_schema}
patient_schema = {"medicalRecords.patients": json_schema}
4
InsertEncryptedDocument.cs
var mongoBinariesPath = "<Full path to your Automatic Encryption Shared Library>";
var extraOptions = new Dictionary<string, object>()
{
{ "cryptSharedLibPath", mongoBinariesPath },
};
insert-encrypted-document.go
extraOptions := map[string]interface{}{
"cryptSharedLibPath": "<Full path to your Automatic Encryption Shared Library>",
}
InsertEncryptedDocument.java
Map<String, Object> extraOptions = new HashMap<String, Object>();
extraOptions.put("cryptSharedLibPath", "<Full path to your Automatic Encryption Shared Library>"));
insert_encrypted_document.js
const extraOptions = {
cryptSharedLibPath: "<Full path to your Automatic Encryption Shared Library>",
};
insert_encrypted_document.py
extra_options = {
"cryptSharedLibPath": "<Full path to your Automatic Encryption Shared Library>"
}

참고

자동 암호화 옵션

자동 암호화 옵션은 자동 암호화 공유 라이브러리에 구성 정보를 제공하여 암호화된 필드에 액세스할 때 애플리케이션의 동작을 수정합니다.

자동 암호화 공유 라이브러리에 대해 자세히 알아보려면 CSFLE를 위한 자동 암호화 공유 라이브러리 페이지를 참조하세요.

5

다음 자동 암호화 설정을 사용하여 MongoDB 클라이언트 객체를 인스턴스화합니다.

InsertEncryptedDocument.cs
var clientSettings = MongoClientSettings.FromConnectionString(connectionString);
var autoEncryptionOptions = new AutoEncryptionOptions(
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders,
schemaMap: schemaMap,
extraOptions: extraOptions
);
clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
var secureClient = new MongoClient(clientSettings);
insert-encrypted-document.go
autoEncryptionOpts := options.AutoEncryption().
SetKmsProviders(kmsProviders).
SetKeyVaultNamespace(keyVaultNamespace).
SetSchemaMap(schemaMap).
SetExtraOptions(extraOptions)
secureClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri).SetAutoEncryptionOptions(autoEncryptionOpts))
if err != nil {
return fmt.Errorf("Connect error for encrypted client: %v", err)
}
defer func() {
_ = secureClient.Disconnect(context.TODO())
}()
InsertEncryptedDocument.java
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.autoEncryptionSettings(AutoEncryptionSettings.builder()
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.schemaMap(schemaMap)
.extraOptions(extraOptions)
.build())
.build();
MongoClient mongoClientSecure = MongoClients.create(clientSettings);
insert_encrypted_document.js
const secureClient = new MongoClient(connectionString, {
useNewUrlParser: true,
useUnifiedTopology: true,
autoEncryption: {
keyVaultNamespace,
kmsProviders,
schemaMap: patientSchema,
extraOptions: extraOptions,
},
});
insert_encrypted_document.py
fle_opts = AutoEncryptionOpts(
kms_providers, key_vault_namespace, schema_map=patient_schema, **extra_options
)
secureClient = MongoClient(connection_string, auto_encryption_opts=fle_opts)
4

CSFLE 지원 MongoClient 인스턴스를 사용하여 다음 코드 스니펫을 사용하여 암호화된 문서를 medicalRecords.patients 네임스페이스에 삽입합니다.

InsertEncryptedDocument.cs
var sampleDocFields = new BsonDocument
{
{ "name", "Jon Doe" },
{ "ssn", 145014000 },
{ "bloodType", "AB-" },
{
"medicalRecords", new BsonArray
{
new BsonDocument("weight", 180),
new BsonDocument("bloodPressure", "120/80")
}
},
{
"insurance", new BsonDocument
{
{ "policyNumber", 123142 },
{ "provider", "MaestCare" }
}
}
};
// Construct an auto-encrypting client
var secureCollection = secureClient.GetDatabase(db).GetCollection<BsonDocument>(coll);
// Insert a document into the collection
secureCollection.InsertOne(sampleDocFields);
insert-encrypted-document.go
test_patient := map[string]interface{}{
"name": "Jon Doe",
"ssn": 241014209,
"bloodType": "AB+",
"medicalRecords": []map[string]interface{}{{
"weight": 180,
"bloodPressure": "120/80",
}},
"insurance": map[string]interface{}{
"provider": "MaestCare",
"policyNumber": 123142,
},
}
if _, err := secureClient.Database(dbName).Collection(collName).InsertOne(context.TODO(), test_patient); err != nil {
return fmt.Errorf("InsertOne error: %v", err)
}

참고

원시 BSON 문서를 만드는 대신 bson 태그가 있는 구조체를 드라이버에 직접 전달하여 인코딩할 수 있습니다.

InsertEncryptedDocument.java
ArrayList<Document> medicalRecords = new ArrayList<>();
medicalRecords.add(new Document().append("weight", "180"));
medicalRecords.add(new Document().append("bloodPressure", "120/80"));
Document insurance = new Document()
.append("policyNumber", 123142)
.append("provider", "MaestCare");
Document patient = new Document()
.append("name", "Jon Doe")
.append("ssn", 241014209)
.append("bloodType", "AB+")
.append("medicalRecords", medicalRecords)
.append("insurance", insurance);
mongoClientSecure.getDatabase(recordsDb).getCollection(recordsColl).insertOne(patient);
insert_encrypted_document.js
try {
const writeResult = await secureClient
.db(db)
.collection(coll)
.insertOne({
name: "Jon Doe",
ssn: 241014209,
bloodType: "AB+",
medicalRecords: [{ weight: 180, bloodPressure: "120/80" }],
insurance: {
policyNumber: 123142,
provider: "MaestCare",
},
});
} catch (writeError) {
console.error("writeError occurred:", writeError);
}
insert_encrypted_document.py
def insert_patient(
collection, name, ssn, blood_type, medical_records, policy_number, provider
):
insurance = {"policyNumber": policy_number, "provider": provider}
doc = {
"name": name,
"ssn": ssn,
"bloodType": blood_type,
"medicalRecords": medical_records,
"insurance": insurance,
}
collection.insert_one(doc)
medical_record = [{"weight": 180, "bloodPressure": "120/80"}]
insert_patient(
secureClient.medicalRecords.patients,
"Jon Doe",
241014209,
"AB+",
medical_record,
123142,
"MaestCare",
)

문서를 삽입하면 CSFLE 활성화 클라이언트는 다음과 유사하도록 문서의 필드를 암호화합니다.

{
"_id": { "$oid": "<_id of your document>" },
"name": "Jon Doe",
"ssn": {
"$binary": "<cipher-text>",
"$type": "6"
},
"bloodType": {
"$binary": "<cipher-text>",
"$type": "6"
},
"medicalRecords": {
"$binary": "<cipher-text>",
"$type": "6"
},
"insurance": {
"provider": "MaestCare",
"policyNumber": {
"$binary": "<cipher-text>",
"$type": "6"
}
}
}

참조: 코드 완성

암호화된 문서를 삽입하기 위한 전체 코드를 보려면 Github 리포지토리 를 참조하세요.

암호화된 문서를 삽입하기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

암호화된 문서를 삽입하기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

암호화된 문서를 삽입하기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

암호화된 문서를 삽입하기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

5

이 가이드의 암호화된 필드가 있는 문서 삽입 단계에서 삽입한 암호화된 문서를 검색합니다.

다음 코드 스니펫은 자동 CSFLE를 사용하도록 구성된 클라이언트와 자동 CSFLE를 사용하도록 구성되지 않은 클라이언트를 사용하여 문서에 대해 쿼리함으로써 CSFLE의 기능을 보여 줍니다.

InsertEncryptedDocument.cs
Console.WriteLine("Finding a document with regular (non-encrypted) client.");
var filter = Builders<BsonDocument>.Filter.Eq("name", "Jon Doe");
var regularResult = regularCollection.Find(filter).Limit(1).ToList()[0];
Console.WriteLine($"\n{regularResult}\n");
Console.WriteLine("Finding a document with encrypted client, searching on an encrypted field");
var ssnFilter = Builders<BsonDocument>.Filter.Eq("ssn", 145014000);
var secureResult = secureCollection.Find(ssnFilter).Limit(1).First();
Console.WriteLine($"\n{secureResult}\n");
insert-encrypted-document.go
fmt.Println("Finding a document with regular (non-encrypted) client.")
var resultRegular bson.M
err = regularClient.Database(dbName).Collection(collName).FindOne(context.TODO(), bson.D{{"name", "Jon Doe"}}).Decode(&resultRegular)
if err != nil {
panic(err)
}
outputRegular, err := json.MarshalIndent(resultRegular, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", outputRegular)
fmt.Println("Finding a document with encrypted client, searching on an encrypted field")
var resultSecure bson.M
err = secureClient.Database(dbName).Collection(collName).FindOne(context.TODO(), bson.D{{"ssn", "241014209"}}).Decode(&resultSecure)
if err != nil {
panic(err)
}
outputSecure, err := json.MarshalIndent(resultSecure, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", outputSecure)
InsertEncryptedDocument.java
System.out.println("Finding a document with regular (non-encrypted) client.");
Document docRegular = mongoClientRegular.getDatabase(recordsDb).getCollection(recordsColl).find(eq("name", "Jon Doe")).first();
System.out.println(docRegular.toJson());
System.out.println("Finding a document with encrypted client, searching on an encrypted field");
Document docSecure = mongoClientSecure.getDatabase(recordsDb).getCollection(recordsColl).find(eq("ssn", 241014209)).first();
System.out.println(docSecure.toJson());
insert_encrypted_document.js
console.log("Finding a document with regular (non-encrypted) client.");
console.log(
await regularClient.db(db).collection(coll).findOne({ name: /Jon/ })
);
console.log(
"Finding a document with encrypted client, searching on an encrypted field"
);
console.log(
await secureClient.db(db).collection(coll).findOne({ ssn: "241014209" })
);
insert_encrypted_document.py
print("Finding a document with regular (non-encrypted) client.")
result = regularClient.medicalRecords.patients.find_one({"name": "Jon Doe"})
pprint.pprint(result)
print("Finding a document with encrypted client, searching on an encrypted field")
pprint.pprint(secureClient.medicalRecords.patients.find_one({"ssn": 241014209}))

이전 코드 스니펫의 출력은 다음과 같아야 합니다.

Finding a document with regular (non-encrypted) client.
{
_id: new ObjectId("629a452e0861b3130887103a"),
name: 'Jon Doe',
ssn: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e7910c20697e5f4fa95710aafc9153f0a3dc769c8a132a604b468732ff1f4d8349ded3244b59cbfb41444a210f28b21ea1b6c737508d9d30e8baa30c1d8070c4d5e26", "hex"), 6),
bloodType: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e79022e238536dfd8caadb4d7751ac940e0f195addd7e5c67b61022d02faa90283ab69e02303c7e4001d1996128428bf037dea8bbf59fbb20c583cbcff2bf3e2519b4", "hex"), 6),
'key-id': 'demo-data-key',
medicalRecords: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e790405163a3207cff175455106f57eef14e5610c49a99bcbd14a7db9c5284e45e3ee30c149354015f941440bf54725d6492fb3b8704bc7c411cff6c868e4e13c58233c3d5ed9593eca4e4d027d76d3705b6d1f3b3c9e2ceee195fd944b553eb27eee69e5e67c338f146f8445995664980bf0", "hex"), 6),
insurance: {
policyNumber: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e79108decd85c05be3fec099e015f9d26d9234605dc959cc1a19b63072f7ffda99db38c7b487de0572a03b2139ac3ee163bcc40c8508f366ce92a5dd36e38b3c742f7", "hex"), 6),
provider: 'MaestCare'
}
}
Finding a document with encrypted client, searching on an encrypted field
{
_id: new ObjectId("629a452e0861b3130887103a"),
name: 'Jon Doe',
ssn: 241014209,
bloodType: 'AB+',
'key-id': 'demo-data-key',
medicalRecords: [ { weight: 180, bloodPressure: '120/80' } ],
insurance: { policyNumber: 123142, provider: 'MaestCare' }
}

참조: 코드 완성

암호화된 문서를 찾기 위한 전체 코드를 보려면 Github 리포지토리

암호화된 문서를 찾기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

암호화된 문서를 찾기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

암호화된 문서를 찾기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

암호화된 문서를 찾기 위한 전체 코드를 보려면 Github 리포지토리를 참조하세요.

CSFLE 작동 방식을 알아보려면 기본 사항을 참조하세요.

이 가이드에 언급된 주제에 대해 자세히 알아보려면 다음 링크를 참조하세요:

  • CSFLE 구성 요소에 대한 자세한 내용은 참조 페이지에서 확인하세요.

  • 키 및 키 볼트 페이지에서 고객 마스터 키와 데이터 암호화 키가 어떻게 작동하는지 알아보세요.

  • KMS 제공자가 CSFLE 키를 관리하는 방법은 CSFLE KMS 제공자 페이지에서 확인하세요.

돌아가기

자습서

다음

Azure에서 자동 클라이언트 측 필드 수준 암호화 사용