이 가이드에서 EF Core Provider를 사용하여 Queryable Encryption (QE)를 사용하여 특정 문서 필드를 암호화하는 방법을 학습할 수 있습니다.
개요
Queryable Encryption은 데이터를 MongoDB에 쓰기 전에 애플리케이션 계층에서 중요한 문서 필드를 암호화하면서도 애플리케이션이 해당 필드를 쿼리할 수 있도록 합니다. 암호화 키에 액세스할 수 있는 애플리케이션만 일반 텍스트 데이터를 읽을 수 있습니다. 공격자가 데이터베이스에 액세스하는 경우 암호화 키에 대한 액세스 권한이 없기 때문에 암호화 텍스트만 볼 수 있습니다.
예를 들어 Queryable Encryption을 사용하여 다음을 포함하는 필드를 암호화할 수 있습니다.
사회 보장 번호
신용 카드 번호
건강 또는 의료 정보
재무 정보
기타 민감한 정보 또는 개인 식별 정보
EF Core 제공자는 유참한 모델 API를 통해 Queryable Encryption을 지원합니다. OnModelCreating() 메서드를 사용하여 암호화할 객체 속성을 구성하면 제공자가 데이터를 읽고 쓰는 동안 자동으로 암호화를 처리합니다.
전제 조건
EF Core 제공자로 Queryable Encryption을 구성하기 전에 다음을 확인하세요.
MongoDB 7.0 이상을 실행하는 MongoDB Enterprise 또는 MongoDB Atlas 클러스터.
Access to a KMS(Key Management Service). 지원되는 KMS 제공자에는 Amazon Web Services, Azure, Google Cloud Platform, KMIP(키 관리 상호 운영 프로토콜) 및 로컬 키 제공자가 포함됩니다.
사용자 환경에 설치된 자동 암호화 공유 라이브러리(
CRYPT_SHARED) 또는mongocryptd. 공유 라이브러리 설치 방법에 대해 학습하려면 MongoDB Server 도서에서 쿼리 분석 컴포넌트 설치 를 참조하세요.
Queryable Encryption 활성화
다음 섹션에서는 컨텍스트에서 암호화 옵션을 구성하고 모델에서 암호화할 엔티티 속성을 표시하는 방법을 설명합니다.
암호화 옵션 구성
Queryable Encryption을 사용하는 컨텍스트를 구성하기 전에 다음 코드를 실행하여 애플리케이션에 대해 자동 암호화 제공자를 한 번 등록해야 합니다.
MongoClientSettings.Extensions.AddAutoEncryption();
그 다음 MongoOptionsExtension 인스턴스를 만들고 인스턴스를 UseMongoDB() 메서드에 전달하기 전에 다음 메서드를 연결합니다.
WithKmsProviders()— KMS 제공자와 자격 증명을 지정합니다.WithKeyVaultNamespace()데이터 암호화 키를 저장하는 데 사용되는 컬렉션을 지정합니다.WithCryptProvider()— 사용할 암호화 라이브러리와 경로를 지정합니다.
다음 예시는 개발 사용을 위해 로컬 KMS 제공자를 구성합니다.
var kmsProviders = new Dictionary< string, IReadOnlyDictionary<string, object>> { { "local", new Dictionary<string, object> { { "key", localMasterKey } } } }; var keyVaultNamespace = CollectionNamespace.FromFullName( "encryption.__keyVault"); var mongoOptions = new MongoOptionsExtension() .WithConnectionString(connectionString) .WithDatabaseName("myDatabase") .WithKmsProviders(kmsProviders) .WithKeyVaultNamespace(keyVaultNamespace) .WithCryptProvider( CryptProvider.AutoEncryptSharedLibrary, Environment.GetEnvironmentVariable("CRYPT_SHARED_LIB_PATH")); var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>() .UseMongoDB(mongoOptions);
공유 라이브러리 대신 mongocryptd 을 사용하려면 CryptProvider.Mongocryptd 과 mongocryptd 바이너리의 경로를 WithCryptProvider() 메서드에 전달합니다.
경고
프로덕션에서 로컬 KMS 제공자를 사용하지 마십시오. 원격 KMS가 없으면 마스터 키에 대한 무단 액세스 위험이 있거나 데이터를 복호화하는 데 필요한 키를 영구적으로 잃을 위험이 있습니다.
암호화할 필드 표시
OnModelCreating() 메서드에서 암호화하려는 각 속성에 대해 암호화 메서드를 호출합니다. 선택한 메서드에 따라 해당 필드에서 사용 가능한 쿼리 유형이 제어됩니다.
메서드 | 쿼리 지원 | 참고 사항 |
|---|---|---|
| none | 쿼리 지원 없이 필드를 암호화합니다. 저장하지만 직접 필터링하지 않는 필드에 사용합니다. |
| 등식( |
|
| 범위( |
|
스캘라 속성보다 소유 엔티티를 암호화하려면 OwnsOne() 또는 OwnsMany()에서 반환된 OwnedNavigationBuilder 또는 OwnershipBuilder 에서 IsEncrypted(dataKeyId) 를 호출합니다.
앞선 방법을 사용하는 전체 예시는 예시: 환자 데이터 암호화됨 섹션을 참조하십시오.
예시: 환자 데이터 암호화
다음 Patient 엔티티는 SSN 및 DateOfBirth 필드를 암호화하는 document model을 정의합니다.
public class Patient { public ObjectId Id { get; set; } public string Name { get; set; } = null!; public string SSN { get; set; } = null!; public DateTime DateOfBirth { get; set; } }
다음 HospitalContext 은 OnModelCreating() 방법에서 암호화될 필드를 표시합니다. SSN 는 쿼리 지원 없이 암호화되고, DateOfBirth 는 범위 쿼리 지원이 있이 암호화됩니다. 생성자는 컨텍스트를 초기화하기 전에 키 보고소에서 만들어 두 개의 데이터 암호화 키의 ID를 허용합니다.
public class HospitalContext : DbContext { public DbSet<Patient> Patients { get; set; } = null!; private readonly Guid _ssnDataKeyId; private readonly Guid _dobDataKeyId; public HospitalContext( DbContextOptions options, Guid ssnDataKeyId, Guid dobDataKeyId) : base(options) { _ssnDataKeyId = ssnDataKeyId; _dobDataKeyId = dobDataKeyId; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Patient>(entity => { entity.ToCollection("patients"); entity.Property(p => p.SSN) .IsEncrypted(_ssnDataKeyId); entity.Property(p => p.DateOfBirth) .IsEncryptedForRange( new DateTime(1900, 1, 1), new DateTime(2100, 12, 31), _dobDataKeyId); }); } }
다음 코드는 암호화 옵션을 구성하고 데이터 키 ID로 HospitalContext 를 인스턴스화하며 Patient 문서를 삽입하고 쿼리합니다.
var mongoOptions = new MongoOptionsExtension() .WithConnectionString("<connection string URI>") .WithDatabaseName("hospitalDb") .WithKmsProviders(kmsProviders) .WithKeyVaultNamespace(keyVaultNamespace) .WithCryptProvider( CryptProvider.AutoEncryptSharedLibrary, Environment.GetEnvironmentVariable("CRYPT_SHARED_LIB_PATH")); using var context = new HospitalContext( new DbContextOptionsBuilder<HospitalContext>() .UseMongoDB(mongoOptions) .Options, ssnDataKeyId, dobDataKeyId); context.Database.EnsureCreated(); context.Patients.Add(new Patient { Name = "John Doe", SSN = "123-45-6789", DateOfBirth = new DateTime(1985, 6, 15) }); context.SaveChanges(); var results = context.Patients .Where(p => p.DateOfBirth > new DateTime(1980, 1, 1)) .ToList();
서버 측 스키마 지원
기본적으로 EF Core 제공자는 필드 암호화 구성을 클라이언트에만 적용합니다. 클라이언트에서만 암호화는 암호화 스키마가 여전히 진행 중인 개발 동안에 적절합니다.
생산 배포서버의 경우 컬렉션을 만들 때 서버에 암호화 스키마를 등록합니다. 서버에 스키마가 있으면 클라이언트 구성과 무관하게 암호화가 시행되어 잘못 구성된 클라이언트의 의도치 않은 평문 쓰기를 방지합니다. 서버에 스키마를 등록한 후에는 컬렉션을 다시 만들지 않으면 암호화되는 필드를 변경할 수 없습니다.
서버 측 스키마로 컬렉션을 만들려면 문맥의 Model 을 QueryableEncryptionSchemaGenerator.GenerateSchemas()에 전달합니다. 그 다음 다음 예시에 나와 있는 것에서처럼 결과를 CreateCollection() 메서드에 전달합니다.
var encryptedSchemas = QueryableEncryptionSchemaGenerator.GenerateSchemas( context.Model); using var client = new MongoClient( "<connection string URI>"); var database = client.GetDatabase("hospitalDb"); foreach (var entityType in context.Model .GetEntityTypes() .Where(e => e.IsDocumentRoot())) { var collectionName = entityType.GetCollectionName(); if (encryptedSchemas.TryGetValue( collectionName, out var schema)) { database.CreateCollection( collectionName, new CreateCollectionOptions { EncryptedFields = schema }); } } context.Database.EnsureCreated();
암호화된 컬렉션이 서버에 존재하면 새 컨텍스트 인스턴스가 서버 스키마만 사용하도록 구성할 수 있습니다. 다음 예시에 표시된 것처럼 MongoOptionsExtension에 QueryableEncryptionSchemaMode.Ignore 을 설정합니다.
var mongoOptions = new MongoOptionsExtension() .WithConnectionString("<connection string URI>") .WithDatabaseName("hospitalDb") .WithKmsProviders(kmsProviders) .WithKeyVaultNamespace(keyVaultNamespace) .WithCryptProvider( CryptProvider.AutoEncryptSharedLibrary, Environment.GetEnvironmentVariable("CRYPT_SHARED_LIB_PATH")) .WithQueryableEncryptionSchemaMode( QueryableEncryptionSchemaMode.Ignore);
Ignore 모드에서는 OnModelCreating() 메서드의 IsEncrypted 구성이 암호화에 영향을 주지 않습니다. 서버 스키마는 암호화될 필드를 제어합니다.
추가 정보
Queryable Encryption 에 대해 자세히 알아보려면 MongoDB Server 매뉴얼의 Queryable Encryption 및 Queryable Encryption 사용 사례 섹션을 참조하세요.
구현에 대한 자세한 내용은 EF Core 제공자 API 문서를 참조하세요.