문서 메뉴
문서 홈
/ / /
몽고이드
/

자동 클라이언트 사이드 필드 레벨 암호화

이 페이지의 내용

  • 설치
  • 설치 libmongocrypt
  • 자동 암호화 공유 라이브러리 설치(Ruby 드라이버 2.19+)
  • mongocryptd 설치(Ruby 드라이버 2.18 이전 버전)
  • Gemfile에 ffi 추가
  • 고객 마스터 키 생성
  • 클라이언트 구성
  • 데이터 암호화 키 생성
  • 암호화 스키마 구성
  • 알려진 제한 사항
  • 데이터와 함께 작업하기
  • 암호화 키 관리(Encryption Key Management)
  • 고객 마스터 키
  • 데이터 암호화 키
  • 암호화 키 순환
  • 기존 프로젝트에 자동 암호화 추가

버전 4.2 이후 MongoDB는 CSFLE(클라이언트 측 필드 레벨 암호화)를 지원합니다. 이는 네트워크를 통해 MongoDB로 전송하기 전에 애플리케이션의 데이터를 암호화할 수 있는 기능입니다. CSFLE를 활성화하면 어떤 MongoDB 제품도 암호화되지 않은 형식의 데이터에 액세스할 수 없습니다.

다음 메커니즘을 사용하여 CSFLE를 설정할 수 있습니다.

  • 자동 암호화: 필드 암호화 방법을 지정하는 코드를 작성할 필요 없이 암호화된 읽기 및 쓰기 작업을 수행할 수 있습니다.

  • 명시적 암호화: MongoDB 드라이버의 암호화 라이브러리를 통해 암호화된 읽기 및 쓰기 작업을 수행할 수 있습니다. 애플리케이션 전체에서 이 라이브러리를 사용하여 암호화 로직을 지정해야 합니다.

버전 9.0 부터 시작됩니다. Mongoid는 CSFLE의 자동 암호화 기능을 지원합니다. 이 튜토리얼에서는 Mongoid에서 CSFLE를 설정하고 사용하는 프로세스를 안내합니다.

참고

이 튜토리얼에서는 모든 CSLFE 기능을 다루지 않습니다. MongoDB CSFLE에 대한 자세한 내용은 서버 설명서에서 확인할 수 있습니다.

참고

명시적 FLE를 사용하려면 Ruby 드라이버 설명서를 따르세요.

필요한 종속성을 설치하는 방법에 대한 자세한 설명은 드라이버 설명서에서 확인할 수 있습니다.

애플리케이션에서 사용 중인 Ruby 드라이버의 버전을 확인하고 아래에서 적절한 단계를 선택하세요.

이 작업은 두 가지 방법 중 하나로 수행할 수 있습니다.

드라이버 버전 이상을 Ruby 2.19 사용하는 경우, Queryable Encryption 매뉴얼의 MongoDB Server 을 위한 자동 암호화 공유 라이브러리 페이지의 지침에 따라 자동 암호화 공유 라이브러리를 설치해야 합니다.

필요한 단계는 다음과 같습니다.

  1. MongoDB 다운로드 센터로 이동

  2. 버전 드롭다운에서 x.y.z (current) (최신 현재 버전)을 선택합니다.

  3. Platform(플랫폼) 드롭다운에서 플랫폼을 선택합니다.

  4. 패키지 드롭다운에서 crypt_shared 을 선택합니다.

  5. 다운로드를 클릭합니다.

추출이 완료되면 라이브러리의 전체 경로가 다음과 같이 mongoid.yml 내에 구성되어 있는지 확인합니다.

development:
clients:
default:
options:
auto_encryption_options:
extra_options:
crypt_shared_lib_path: '/path/to/mongo_crypt_v1.so'

이전 버전의 Ruby 드라이버를 사용하는 경우 mongocryptd 을(를) 수동으로 설치해야 합니다. mongocryptd 은(는) MongoDB 서버의 엔터프라이즈 빌드(버전 4.2 이상)와 함께 사전 패키징되어 제공됩니다. 설치 지침은 MongoDB 매뉴얼 을 참조하세요.

MongoDB Ruby 드라이버는 ffi gemlibmongocrypt 사용합니다. 에서 함수를 호출합니다. 이 gem은 드라이버의 종속성이 아니므로 Gemfile 에 수동으로 추가해야 합니다.

gem 'ffi'

고객 마스터 키(CMK)는 데이터 암호화 키를 암호화하는 데 사용됩니다. 가장 쉬운 방법은 로컬에 저장된 96바이트 키를 사용하는 것입니다. 다음 Ruby 코드를 사용하여 이러한 키를 생성할 수 있습니다.

require 'securerandom'
SecureRandom.hex(48) # => "f54ab...."

이 튜토리얼의 뒷부분에서는 CUSTOMER_MASTER_KEY 환경 변수에서 고객 마스터 키를 사용할 수 있다고 가정합니다.

경고

로컬 마스터 키를 사용하는 것은 안전하지 않습니다. 원격 KMS를 사용하여 마스터 키를 생성하고 저장하는 것이 좋습니다. 이렇게 하려면 MongoDB 클라이언트 측 암호화 문서에서 "원격 마스터 키 설정" 단계를 따르세요.

마스터 키 생성에 대한 자세한 내용은 MongoDB 매뉴얼의 고객 마스터 키 생성 섹션을 참조하세요.

자동 CSFLE를 사용하려면 MongoDB 클라이언트에 대한 몇 가지 추가 구성이 필요합니다. 애플리케이션에 default 클라이언트가 하나만 있다고 가정하면 mongoid.yml 에 다음을 추가해야 합니다.

development:
clients:
default:
uri: mongodb+srv://user:pass@yourcluster.mongodb.net/blog_development?retryWrites=true&w=majority
options:
auto_encryption_options: # This key enables automatic encryption
key_vault_namespace: 'encryption.__keyVault' # Database and collection to store data keys
kms_providers: # Tells the driver where to obtain master keys
local: # We use the local key in this tutorial
key: "<%= ENV['CUSTOMER_MASTER_KEY'] %>" # Key that we generated earlier
extra_options:
crypt_shared_lib_path: '/path/to/mongo_crypt_v1.so' # Only if you use the library

DEK(데이터 암호화 키)는 MongoDB 문서의 필드를 암호화하는 데 사용하는 키입니다. CMK로 암호화된 키 볼트 컬렉션에 데이터 암호화 키를 저장합니다.

Mongoid에서 DEK를 만들려면 db:mongoid:encryption:create_data_key Rake 작업을 사용할 수 있습니다.

% rake db:mongoid:encryption:create_data_key
Created data key with id: 'KImyywsTQWi1+cFYIHdtlA==' for kms provider: 'local' in key vault: 'encryption.__keyVault'.

필요한 경우 DEK를 여러 개 만들 수 있습니다.

% rake db:mongoid:encryption:create_data_key
Created data key with id: 'Vxr5m+5cQISjDOruzZgE0w==' for kms provider: 'local' in key vault: 'encryption.__keyVault'.

DEK의 대체 이름을 제공할 수도 있습니다. 이렇게 하면 필드에 대한 암호화를 구성할 때 이름으로 DEK를 참조할 수 있습니다. 또한 런타임에 필드에 DEK를 동적으로 할당할 수 있습니다.

% rake db:mongoid:encryption:create_data_key -- --key-alt-name=my_data_key
Created data key with id: 'yjF8hKmKQsqGeFGXlB9Sow==' with key alt name: 'my_data_key' for kms provider: 'local' in key vault: 'encryption.__keyVault'.

이제 Mongoid에 무엇을 암호화해야 하는지 알릴 수 있습니다.

class Patient
include Mongoid::Document
include Mongoid::Timestamps
# Tells Mongoid what DEK should be used to encrypt fields of the document
# and its embedded documents.
encrypt_with key_id: 'KImyywsTQWi1+cFYIHdtlA=='
# This field is not encrypted.
field :category, type: String
# This field is encrypted using AEAD_AES_256_CBC_HMAC_SHA_512-Random
# algorithm.
field :passport_id, type: String, encrypt: {
deterministic: false
}
# This field is encrypted using AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic
# algorithm.
field :blood_type, type: String, encrypt: {
deterministic: true
}
# This field is encrypted using AEAD_AES_256_CBC_HMAC_SHA_512-Random
# algorithm and using a different data key.
field :ssn, type: Integer, encrypt: {
deterministic: false, key_id: 'Vxr5m+5cQISjDOruzZgE0w=='
}
embeds_one :insurance
end
class Insurance
include Mongoid::Document
include Mongoid::Timestamps
field :insurer, type: String
# This field is encrypted using AEAD_AES_256_CBC_HMAC_SHA_512-Random
# algorithm using the key which alternate name is stored in the
# policy_number_key field.
field :policy_number, type: Integer, encrypt: {
deterministic: false,
key_name_field: :policy_number_key
}
embedded_in :patient
end

참고

Rails 애플리케이션을 개발하는 경우 preload_models true mongoid.yml에서 를 로 설정하는 것이 좋습니다. 이렇게 하면 애플리케이션이 시작되기 전에 Mongoid가 모든 모델을 로드하고 데이터를 읽거나 쓰기 전에 암호화 스키마를 구성합니다.

  • MongoDB CSFLE에는 MongoDB Server 매뉴얼의 CSFLE 제한 페이지에 설명된 몇 가지 제한 사항이 있습니다. 이러한 제한 사항은 Mongoid에도 적용됩니다.

  • Mongoid는 embeds_many 관계의 암호화를 지원하지 않습니다.

  • :key_name_field 옵션을 사용하는 경우 비결정적 알고리즘을 사용하여 필드를 암호화해야 합니다. 필드를 결정론적으로 암호화하려면 대신 :key_id 옵션을 지정해야 합니다.

자동 CSFLE 사용은 많은 상황에서 투명하게 이루어집니다.

참고

아래 코드 예제에서는 동일한 데이터베이스에 연결되었지만 암호화되지 않은 MongoClient 인 변수 unencrypted_client 가 있다고 가정합니다. 이 클라이언트를 사용하여 데이터베이스에 실제로 지속되는 내용을 시연합니다.

문서는 평소와 같이 생성할 수 있으며, 필드는 구성에 따라 암호화되고 해독됩니다.

Patient.create!(
category: 'ER',
passport_id: '123456',
blood_type: 'AB+',
ssn: 98765,
insurance: Insurance.new(insurer: 'TK', policy_number: 123456, policy_number_key: 'my_data_key')
)
# Fields are encrypted in the database
unencrypted_client['patients'].find.first
# =>
# {"_id"=>BSON::ObjectId('6446a1d046ebfd701f9f4292'),
# "category"=>"ER",
# "passport_id"=><BSON::Binary:0x404080 type=ciphertext data=0x012889b2cb0b1341...>,
# "blood_type"=><BSON::Binary:0x404560 type=ciphertext data=0x022889b2cb0b1341...>,
# "ssn"=><BSON::Binary:0x405040 type=ciphertext data=0x012889b2cb0b1341...>,
# "insurance"=>{"_id"=>BSON::ObjectId('6446a1d046ebfd701f9f4293'), "insurer"=>"TK", "policy_number"=><BSON::Binary:0x405920 type=ciphertext data=0x012889b2cb0b1341...>}, "policy_number_key"=>"my_data_key"}

결정론적 알고리즘을 사용하여 암호화된 필드를 쿼리할 수 있습니다. 정확히 일치하는 쿼리만 지원됩니다. 자세한 내용 은 서버 설명서 를 참조하세요.

# We can find documents by deterministically encrypted fields.
Patient.where(blood_type: "AB+").to_a
# => [#<Patient _id: 6447e34d46ebfd3debdd9c39, category: "ER", passport_id: "123456", blood_type: "AB+", ssn: 98765>]

고객 마스터 키는 데이터 암호화 키를 암호화하는 데 사용하는 키입니다. MongoDB는 데이터 암호화 키 생성 중에 지정된 CMK를 사용하여 데이터 암호화 키를 자동으로 암호화합니다.

CMK는 CSFLE에서 가장 민감한 키입니다. CMK가 손상되면 암호화된 모든 데이터를 해독할 수 있습니다.

중요

고객 마스터 키(CMK)를 원격 KMS에 저장해야 합니다.

원격 KMS를 사용해야 하는 이유에 대해 자세히 알아보려면 원격 KMS를 사용해야 하는 이유를 참조하세요.

지원되는 모든 KMS 제공자 목록을 보려면 KMS 제공자 페이지를 참조하세요.

MongoDB CSFLE는 다음과 같은 키 관리 시스템(KMS) 제공자를 지원합니다.

데이터 암호화 키는 db:mongoid:encryption:create_data_key Rake 작업을 사용하여 만들 수 있습니다. 기본적으로 데이터베이스와 동일한 클러스터에 저장됩니다. 그러나 키는 별도로 저장하는 것이 좋습니다. 이 작업은 mongoid.yml 에서 Key Vault 클라이언트를 지정하여 수행할 수 있습니다.

development:
clients:
key_vault:
uri: mongodb+srv://user:pass@anothercluster.mongodb.net/blog_development?retryWrites=true&w=majority
default:
uri: mongodb+srv://user:pass@yourcluster.mongodb.net/blog_development?retryWrites=true&w=majority
options:
auto_encryption_options:
key_vault_client: :key_vault # Client to connect to key vault
# ...

Ruby 드라이버의 rewrap_many_data_key 메서드를 사용하여 암호화 키를 순환할 수 있습니다. 이 방법은 여러 데이터 암호화 키를 자동으로 해독하고 지정된 CMK를 사용하여 다시 암호화합니다. 그런 다음 키 볼트 컬렉션에서 순환된 키를 업데이트합니다. 이 메서드를 사용하면 두 가지 선택적 인수를 기반으로 암호화 키를 회전할 수 있습니다.

  • 회전할 키를 지정하는 데 사용되는 필터입니다. 지정된 필터와 일치하는 데이터 키가 없으면 키가 순환되지 않습니다. 키 볼트 컬렉션의 모든 키를 순환시키려면 필터를 생략하세요.

  • 새 CMK를 나타내는 객체입니다. 현재 CMK를 사용하여 데이터 키를 회전하려면 이 객체를 생략합니다.

다음은 Amazon Web Services KMS 를 사용하여 키를 회전하는 예입니다.

# Create a key vault client
key_vault_client = Mongo::Client.new('mongodb+srv://user:pass@yourcluster.mongodb.net')
# Or, if you declared the key value client in mongoid.yml, use it
key_vault_client = Mongoid.client(:key_vault)
# Create the encryption object
encryption = Mongo::ClientEncryption.new(
key_vault_client,
key_vault_namespace: 'encryption.__keyVault',
kms_providers: {
aws: {
"accessKeyId": "<IAM User Access Key ID>",
"secretAccessKey": "<IAM User Secret Access Key>"
}
}
)
encryption.rewrap_many_data_key(
{}, # We want to rewrap all keys
{
provider: 'aws',
master_key: {
region: 'us-east-2',
key: 'arn:aws:kms:us-east-2:...'
}
}
)

MongoDB 자동 CSFLE는 제자리에서 암호화를 지원합니다. 기존 데이터베이스에 대해 암호화를 활성화할 수 있으며, 암호화되지 않은 데이터는 계속 읽을 수 있습니다. 데이터베이스에 기록된 모든 데이터는 암호화됩니다. 그러나 암호화가 활성화되면 모든 쿼리 작업은 암호화된 데이터를 사용합니다.

# We assume that there are two documents in the database, one created without
# encryption enabled, and one with encryption.
# We can still read both.
Patient.all.to_a
# =>
# [#<Patient _id: 644937ac46ebfd02468e58c8, category: "ER", passport_id: "DE-1257", blood_type: "AB+", ssn: 123456>,
# #<Patient _id: 644937c946ebfd029309b912, category: "ER", passport_id: "AT-1545", blood_type: "AB+", ssn: 987654>]
# But when we query, we can see only the latter one.
Patient.where(blood_type: 'AB+').to_a
# => [#<Patient _id: 644937c946ebfd029309b912, category: "ER", passport_id: "AT-1545", blood_type: "AB+", ssn: 987654>]

기존 데이터베이스를 암호화하려는 경우 변경 사항 없이 모든 데이터를 읽고 다시 기록하면 됩니다. 이렇게 하기로 결정한 경우 다음 사항을 염두에 두세요.

  • 일관된 충실도를 위해 기존 데이터의 무결성을 검증합니다. CSFLE는 유형을 구분합니다. 예를 들어 String 으로 선언된 필드에는 정수를 저장할 수 없습니다.

  • 문자열의 경우 빈 값이 항상 빈 문자열인지 또는 설정되지 않았는지 확인하되 nil 은(는) 설정하지 않아야 합니다(CSFLE는 네이티브 null 를 지원하지 않음).

  • 이 작업에는 애플리케이션 다운타임이 필요합니다.

돌아가기

일반적인 오류