Docs Menu
Docs Home
/
MongoDB 매뉴얼
/ / / / /

GCP에서 자동 클라이언트 측 필드 레벨 암호화 사용

이 페이지의 내용

  • 개요
  • 시작하기 전에
  • 전체 애플리케이션 코드
  • KMS 설정
  • GCP 서비스 계정 등록
  • GCP 고객 마스터 키 만들기
  • 애플리케이션 생성
  • 키 볼트 collection에 고유 인덱스 만들기
  • 데이터 암호화 키 생성
  • MongoClient 구성
  • 암호화된 필드가 있는 문서 삽입하기
  • 암호화된 필드로 문서 검색하기
  • 자세히 알아보기

이 가이드에서는 GCP KMS를 사용하여 CSFLE(클라이언트 측 필드 레벨 암호화) 지원 애플리케이션을 빌드하는 방법을 설명합니다.

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

  • GCP 키 관리 서비스에서 호스팅되는 고객 마스터 키 입니다.

  • CMK 를 사용하여 암호화된 필드가 있는 문서를 삽입하는 클라이언트 애플리케이션입니다.

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

이 가이드 전체에서 코드 예제에는 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.

중요

go build 또는 go run를 사용하여 이 가이드 의 Go 코드를 빌드하거나 실행 때는 항상 cse 빌드 제약 조건을 포함하여 CSFLE 를 활성화 하세요. 빌드 제약 조건을 포함하는 예시 는 다음 shell 명령을 참조하세요.

go run -tags cse insert-encrypted-document.go
// 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. Google Cloud 에기존 계정을 등록하거나 로그 합니다.

  2. 프로젝트에 대한 서비스 계정 만들기

    GCP에서 서비스 계정을 만들려면 서비스 계정 만들기 를 따르세요. 가이드를 참조하세요.

  3. 서비스 계정 키 추가

    GCP에 서비스 계정 키를 추가하려면 서비스 계정 키 관리 하기를 따르세요. 가이드를 참조하세요.

    중요

    서비스 계정 키를 생성할 때 비공개 키 정보를 일회성 다운로드로 받게 됩니다. 이 튜토리얼의 뒷부분에서 사용할 수 있도록 이 파일을 PKCS12 또는 JSON 형식으로 다운로드해야 합니다.

    중요

    서비스 계정 키를 생성할 때 비공개 키 정보를 일회성 다운로드로 받게 됩니다. 이 튜토리얼의 뒷부분에서 사용할 수 있도록 이 파일을 PKCS12 또는 JSON 형식으로 다운로드해야 합니다.

    중요

    서비스 계정 키를 생성하면 비공개 키 정보가 일회성으로 다운로드 됩니다. 연결된 서비스 계정을 사용하지 않는 한 이 튜토리얼의 뒷부분에서 사용할 수 있도록 이 파일 을 PKCS12 또는 JSON 형식으로 다운로드 해야 합니다.

    중요

    서비스 계정 키를 생성할 때 비공개 키 정보를 일회성 다운로드로 받게 됩니다. 이 튜토리얼의 뒷부분에서 사용할 수 있도록 이 파일을 PKCS12 또는 JSON 형식으로 다운로드해야 합니다.

    중요

    서비스 계정 키를 생성할 때 비공개 키 정보를 일회성 다운로드로 받게 됩니다. 이 튜토리얼의 뒷부분에서 사용할 수 있도록 이 파일을 PKCS12 또는 JSON 형식으로 다운로드해야 합니다.

2
  1. 새 고객 마스터 키 생성

    키 생성 단계에 따라 키링과 대칭 키를 생성합니다. 가이드를 참조하세요.

    이 키는 고객 마스터 키(CMK)입니다.

    이 튜토리얼의 이후 단계에서 사용할 수 있도록 고객 마스터 키 에 대한 다음 세부 정보를 기록합니다.

    필드
    필수 사항
    설명
    key_name
    고객 마스터 키 의 식별자입니다.
    key_ring
    키가 속한 키 그룹의 식별자입니다.
    key_version
    No
    명명된 키의 버전입니다.
    위치
    키에 대해 지정된 리전입니다.
    엔드포인트
    No
    Google Cloud KMS의 호스트 및 선택적 포트입니다. 기본값은 cloudkms.googleapis.com 입니다.

애플리케이션에서 사용 중인 MongoDB 드라이버에 해당하는 탭을 선택하면 관련 코드 샘플을 볼 수 있습니다.

1

encryption.__keyVault 네임스페이스의 keyAltNames 필드에 고유 인덱스를 만듭니다.

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

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);
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)
}
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();
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 } },
}
);
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. GCP KMS 자격 증명 추가

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
    var provider = "gcp";
    var gcpKmsOptions = new Dictionary<string, object>
    {
    { "privateKey", "<Your GCP Private Key>" },
    { "email", "<Your GCP Email>" },
    };
    kmsProviders.Add(provider, gcpKmsOptions);

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    provider := "gcp"
    kmsProviders := map[string]map[string]interface{}{
    provider: {
    "email": "<Your GCP Email>",
    "privateKey": "<Your GCP Private Key>",
    },
    }

    연결된 서비스 계정

    연결된 서비스 계정 을 사용하는 경우 , GCP KMS 에 자동으로 인증하도록 허용할 수 있습니다.

    자동으로 인증하려면 다음 코드에 표시된 대로 GCP 자격 증명 이 포함된 맵 대신 빈 맵을 할당합니다.

    String kmsProvider = "gcp";
    Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
    Map<String, Object> providerDetails = new HashMap<>();
    kmsProviders.put(kmsProvider, providerDetails);

    이 코드를 추가한 후 가이드 의 다음 단계로 진행하세요.

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    String kmsProvider = "gcp";
    Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
    Map<String, Object> providerDetails = new HashMap<>();
    providerDetails.put("email", "<Your GCP Email Address>");
    providerDetails.put("privateKey", "<Your GCP Private Key>");
    kmsProviders.put(kmsProvider, providerDetails);

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    const provider = "gcp";
    const kmsProviders = {
    gcp: {
    email: "<Your GCP Email>",
    privateKey: "<Your GCP Private Key>",
    },
    };

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    provider = "gcp"
    kms_providers = {
    provider: {"email": "<your GCP email>", "privateKey": "<your GCP private key>"}
    }

    이 가이드 의 GCP 서비스 계정 만들기 단계에서 서비스 계정 키 자격 증명이 포함된 파일을 저장했습니다.

    자격 증명을 JSON 형식으로 다운로드한 경우 다음 명령을 사용하여 자격 증명 파일의 이름으로 <credentials-filename> 를 대체하여 비공개 키 값을 추출할 수 있습니다. 다음 명령을 사용하려면 OpenSSL을 설치해야 합니다.

    cat <credentials-filename> | jq -r .private_key | openssl pkcs8 -topk8 -nocrypt -inform PEM -outform DER | base64

    자격 증명을 PKCS12 형식으로 다운로드한 경우, GCP 서비스 계정 가져오기 암호를 지정하고 PEM 암호 구문을 추가하여 다음 명령을 사용하여 키에 액세스할 때 키에 액세스해야 하며, 이때 <credentials-filename> 을 자격 증명 파일의 이름으로 대체합니다.

    openssl pkcs12 -info -in <credentials-filename>
  2. 키 정보 추가

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

    이 가이드 의 고객 마스터 키 생성 단계에서 고객 마스터 키 세부 정보를 기록했습니다.

    var dataKeyOptions = new DataKeyOptions(
    masterKey: new BsonDocument
    {
    { "projectId", "Your GCP Project ID" },
    { "location", "Your GCP Key Location" } ,
    { "keyRing", "<Your GCP Key Ring>" },
    { "keyName", "<Your GCP Key Name>" },
    });
    masterKey := map[string]interface{}{
    "projectId": "<Your GCP Project ID>",
    "location": "<Your GCP Location>",
    "keyRing": "<Your GCP Key Ring>",
    "keyName": "<Your GCP Key Name>",
    }
    BsonDocument masterKeyProperties = new BsonDocument();
    masterKeyProperties.put("provider", new BsonString(kmsProvider));
    masterKeyProperties.put("projectId", new BsonString("<Your GCP Project ID>"));
    masterKeyProperties.put("location", new BsonString("<Your GCP Key Location>"));
    masterKeyProperties.put("keyRing", new BsonString("<Your GCP Key Ring>"));
    masterKeyProperties.put("keyName", new BsonString("<Your GCP Key Name>"));
    const masterKey = {
    projectId: "<Your Project ID>",
    location: "<Your Key Location>",
    keyRing: "<Your Key Ring>",
    keyName: "<Your Key Name>",
    };
    master_key = {
    "projectId": "<GCP project identifier>",
    "location": "<GCP region>",
    "keyRing": "<GCP key ring name>",
    "keyName": "<GCP key name>",
    }
  3. 데이터 암호화 키 생성

    이 튜토리얼의 1단계에서 선언한 변수를 사용하여 데이터 암호화 키를 생성합니다.

    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}");
    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))
    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();
    const client = new MongoClient(uri);
    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();

    참고

    클라이언트 암호화 가져오기

    Node.js 드라이버 v6.0 이상을 사용하는 경우 mongodb에서 ClientEncryption을(를) 가져와야 합니다.

    이전 드라이버 버전의 경우 mongodb-client-encryption에서 ClientEncryption을(를) 가져옵니다.

    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)

자세히 알아보기

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

Azure Key Vault에서 호스팅되는 고객 마스터 키로 암호화된 데이터 암호화 키를 생성하는 옵션에 대해 자세히 알아보려면 kmsProviders 객체dataKeyOpts 객체를 참조하세요.

참조: 코드 완성

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

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

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

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

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

3

이전 단계에서 생성된 파일과 별도의 파일에서 이 튜토리얼의 나머지 단계를 따르세요.

이 파일 의 전체 코드를 보려면 Github 리포지토리 를 참조하세요.

이 파일의 전체 코드를 보려면 Github 리포지토리를 참조하세요.

이 파일의 전체 코드를 보려면 Github 리포지토리를 참조하세요.

이 파일의 전체 코드를 보려면 Github 리포지토리를 참조하세요.

이 파일의 전체 코드를 보려면 Github 리포지토리를 참조하세요.

  1. 키 볼트 collection 네임스페이스 지정하기

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

    var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
    keyVaultNamespace := "encryption.__keyVault"
    String keyVaultNamespace = "encryption.__keyVault";
    const keyVaultNamespace = "encryption.__keyVault";
    key_vault_namespace = "encryption.__keyVault"
  2. cloud 계정 자격 증명 지정

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
    var provider = "gcp";
    var gcpKmsOptions = new Dictionary<string, object>
    {
    { "privateKey", "<Your GCP Private Key>" },
    { "email", "<Your GCP Email>" },
    };
    kmsProviders.Add(provider, gcpKmsOptions);

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    kmsProviders := map[string]map[string]interface{}{
    "gcp": {
    "email": "<Your GCP Email>",
    "privateKey": "<Your GCP Private Key>",
    },
    }

    연결된 서비스 계정

    연결된 서비스 계정 을 사용하는 경우 , GCP KMS 에 자동으로 인증하도록 허용할 수 있습니다.

    자동으로 인증하려면 다음 코드에 표시된 대로 GCP 자격 증명 이 포함된 맵 대신 빈 맵을 할당합니다.

    String kmsProvider = "gcp";
    Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
    Map<String, Object> providerDetails = new HashMap<>();
    kmsProviders.put(kmsProvider, providerDetails);

    이 코드를 추가한 후 가이드 의 다음 단계로 진행하세요.

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    String kmsProvider = "gcp";
    Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
    Map<String, Object> providerDetails = new HashMap<>();
    providerDetails.put("email", "<Your GCP Email Address>");
    providerDetails.put("privateKey", "<Your GCP Private Key>");
    kmsProviders.put(kmsProvider, providerDetails);

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    const kmsProviders = {
    gcp: {
    email: "<Your GCP Email>",
    privateKey: "<Your GCP Private Key>",
    },
    };

    연결된 서비스 계정을 사용하지 않는 한 다음 코드 예제와 같이 CSFLE 지원 클라이언트에 서비스 계정 자격 증명을 추가합니다.

    provider = "gcp"
    kms_providers = {
    "gcp": {"email": "<your GCP email>", "privateKey": "<your GCP private key>"}
    }
  3. 컬렉션에 대한 암호화 스키마 만들기

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

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

    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);
    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,
    }
    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()));
    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;
    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}
  4. 자동 암호화 공유 라이브러리의 위치 지정

    var mongoBinariesPath = "<Full path to your Automatic Encryption Shared Library>";
    var extraOptions = new Dictionary<string, object>()
    {
    { "cryptSharedLibPath", mongoBinariesPath },
    };
    extraOptions := map[string]interface{}{
    "cryptSharedLibPath": "<Full path to your Automatic Encryption Shared Library>",
    }
    Map<String, Object> extraOptions = new HashMap<String, Object>();
    extraOptions.put("cryptSharedLibPath", "<Full path to your Automatic Encryption Shared Library>"));
    const extraOptions = {
    cryptSharedLibPath: "<Full path to your Automatic Encryption Shared Library>",
    };
    extra_options = {
    "cryptSharedLibPath": "<Full path to your Automatic Encryption Shared Library>"
    }

    참고

    자동 암호화 옵션

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

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

  5. MongoClient 생성

    이전 단계에서 선언된 변수를 사용하는 다음 자동 암호화 설정으로 MongoDB 클라이언트 객체를 인스턴스화합니다.

    MongoClientSettings.Extensions.AddAutoEncryption(); // .NET/C# Driver v3.0 or later only
    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);
    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);
    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())
    }()
    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);
    const secureClient = new MongoClient(connectionString, {
    autoEncryption: {
    keyVaultNamespace,
    kmsProviders,
    schemaMap: patientSchema,
    extraOptions: extraOptions,
    },
    });
    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 네임스페이스에 삽입합니다.

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);
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 태그가 있는 구조체를 드라이버에 직접 전달하여 인코딩할 수 있습니다.

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);
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);
}
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의 기능을 보여 줍니다.

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");
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)
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());
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" })
);
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 구성 요소에 대한 자세한 내용은 참조 페이지에서 확인하세요.

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

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

돌아가기

Azure 사용