Docs Menu
Docs Home
/
데이터베이스 매뉴얼
/ / / / /

CSFLE로 삭제 권한 구현

암호화폐 파쇄 샘플 앱 MongoDB의 클라이언트 측 필드 레벨 암호화 (CSFLE) 를 사용하여 민감한 데이터를 제거하는 절차를 강화하는 방법을 보여줍니다.

잊힐 권리라고도 하는 삭제 권리는 GDPR 과 같은 법률 및 규정에 따라 개인에게 부여되는 권리입니다. 즉, 개인의 개인 데이터를 저장하는 회사는 요청 시 해당 데이터를 삭제 수 있어야 합니다. 데이터는 여러 시스템에 분산될 수 있으므로 이러한 회사에서 데이터를 모든 위치에서 식별하고 제거 것은 기술적으로 어려울 수 있습니다. 올바르게 실행하더라도 삭제된 데이터가 향후 백업에서 복원되어 법적 및 재정적 위험을 초래할 수 있는 위험이 있습니다.

경고

MongoDB 이 문서에 설명된 솔루션과 기술이 삭제 권리와 관련된 모든 규제 요건을 충족한다는 보장 제공하지 않습니다. 조직 GDPR 과 같은 규제 요구 사항을 준수하기 위해 적절하고 충분한 조치를 결정해야 합니다.

암호화폐 파쇄 샘플 애플리케이션 삭제 권한을 구현 한 가지 방법을 보여줍니다. 데모 애플리케이션 사용자 추가, 로그인, 데이터 입력을 위한 프런트 엔드가 있는 Python (Flask) 웹 애플리케이션 입니다. 또한 암호화폐 파쇄 기능을 보여주는 "관리자" 페이지도 포함되어 있습니다.

Github 리포지토리의 지침에 따라 애플리케이션을 설치하고 실행 수 있습니다.

암호화 삭제라고도 하는 암호화폐 파쇄는 암호화됨 데이터를 파기하는 대신 데이터를 해독하는 데 필요한 암호화 키를 파기하는 데이터 파기 기술입니다. 이로 인해 데이터를 해독할 수 없게 됩니다.

예시 들어 여러 사용자에 대한 데이터를 저장한다고 가정해 보겠습니다. 먼저 각 사용자에게 고유한 DEK 제공하고 이를 해당 고객에 매핑합니다.

다이어그램에서 "사용자 A"와 "사용자 B"는 각각 키 저장 에 고유한 DEK를 가집니다. 각 키는 해당 사용자의 데이터를 암호화하거나 해독하는 데 사용됩니다.

두 명의 사용자가 있는 데이터 암호화 키 저장

사용자 B의 모든 데이터를 제거 한다고 가정해 보겠습니다. 사용자 B의 DEK를 제거 하면 더 이상 해당 데이터를 해독할 수 없습니다. 데이터 저장소의 모든 내용은 해독할 수 없는 암호 텍스트가 됩니다. 사용자 A의 DEK가 여전히 존재하므로 데이터는 영향을 받지 않습니다.

사용자 B의 데이터 암호화 키 삭제

애플리케이션은 CSFLE를 사용하여 데이터를 서버로 전송하기 전에 문서의 민감한 필드를 암호화할 수 있습니다. 메모리의 데이터베이스 에서 데이터를 사용하는 경우에도 일반 텍스트로 저장되지 않습니다. 데이터베이스 클라이언트 만 해독할 수 있는 암호화됨 데이터를 저장하고 전송합니다.

CSFLE는 최상위 엔벨로프 키( ' 고객 마스터 키' 또는 CMK 라고도 함)로 자체 암호화됨 데이터 키로 일반 텍스트 데이터를 암호화하는 방식인 봉투 암호화 사용합니다.

엔벨로프 암호화 다이어그램

CMK는 일반적으로 KMS (KMS )에서 managed . CSFLE는 Amazon Web Services (Amazon Web Services), Azure Key Vault, Google Cloud Platform (GCP), KMIP 표준을 지원 키 저장소(예: Hashicorp Keyvault) 등 여러 KMS를 지원합니다. 샘플 앱 Amazon Web Services KMS 로 사용합니다.

CSFLE는 자동 또는 명시적 모드 또는 이 둘의 조합으로 사용할 수 있습니다. 샘플 앱 명시적 암호화 사용합니다.

  • 자동 암호화 사용하면 정의된 암호화 스키마 기반으로 암호화됨 읽기 및 쓰기 (write) 작업을 수행할 수 있으므로 필드를 암호화하거나 해독하는 방법을 지정하는 애플리케이션 코드가 필요하지 않습니다.

  • 명시적 암호화 사용하면 MongoDB 드라이버의 암호화 라이브러리를 사용하여 애플리케이션 의 필드를 수동으로 암호화하거나 해독할 수 있습니다.

샘플 앱 명시적 암호화 와 함께 CSFLE 를 사용하고 Amazon Web Services KMS 로 사용합니다.

암호화폐 파쇄 UI 예시

app.mongodb_encryption_client 객체 초기화하여 ClientEncryption 클래스를 인스턴스화합니다. 이 암호화 클라이언트 DEK를 생성한 다음 Amazon Web Services KMS 에서 CMK 사용하여 암호화하는 작업을 담당합니다.

사용자가 등록하면 애플리케이션 create_data_key 메서드를 사용하여 고유한 DEK를 생성한 다음 data_key_id을 반환합니다.

# flaskapp/db_queries.py
@aws_credential_handler
def create_key(userId):
data_key_id = \app.mongodb_encryption_client.create_data_key
(kms_provider, master_key, key_alt_names=[userId])
return data_key_id

그런 다음 앱 사용자 정보를 저장할 때 이 메서드를 사용합니다.

# flaskapp/user.py
def save(self):
dek_id = db_queries.create_key(self.username)
result = app.mongodb[db_name].user.insert_one(
{
"username": self.username,
"password_hash": self.password_hash,
"dek_id": dek_id,
"createdAt": datetime.now(),
}
)
if result:
self.id = result.inserted_id
return True
else:
return False

등록이 완료되면 사용자는 로그인 입력 양식을 통해 키-값 쌍으로 데이터를 입력할 수 있습니다.

데이터 추가를 위한 샘플 UI

데이터베이스 이 데이터를 'data'라는 이름의 MongoDB 컬렉션 에 저장하며, 각 문서 에는 사용자 이름 과 키-값 쌍이 포함됩니다.

{
"name": "shoe size",
"value": "10",
"username": "tom"
}

샘플 앱 valueusername 필드를 암호화하지만 name는 암호화하지 않습니다. 앱 사용자의 DEK와 지정된 암호화 알고리즘 사용하여 필드를 암호화합니다.

# flaskapp/db_queries.py
# Fields to encrypt, and the algorithm to encrypt them with
ENCRYPTED_FIELDS = {
# Deterministic encryption for username, because we need to search on it
"username": Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
# Random encryption for value, as we don't need to search on it
"value": Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random,
}

insert_data 함수는 암호화되지 않은 문서 가져와서 ENCRYPTED_FIELDS 루프를 통해 암호화합니다.

# flaskapp/db_queries.py
def insert_data(document):
document["username"] = current_user.username
# Loop over the field names (and associated algorithm) we want to encrypt
for field, algo in ENCRYPTED_FIELDS.items():
# if the field exists in the document, encrypt it
if document.get(field):
document[field] = encrypt_field(document[field], algo)
# Insert document (now with encrypted fields) to the data collection
app.data_collection.insert_one(document)

지정된 필드 문서 에 있는 경우 함수는 encrypt_field 를 호출하여 지정된 알고리즘 사용하여 문서를 암호화합니다.

# flaskapp/db_queries.py
# Encrypt a single field with the given algorithm
@aws_credential_handler
def encrypt_field(field, algorithm):
try:
field = app.mongodb_encryption_client.encrypt(
field,
algorithm,
key_alt_name=current_user.username,
)
return field
except pymongo.errors.EncryptionError as ex:
# Catch this error in case the DEK doesn't exist. Log a warning and
# re-raise the exception
if "not all keys requested were satisfied" in ex._message:
app.logger.warn(
f"Encryption failed: could not find data encryption key for user: {current_user.username}"
)
raise ex

데이터를 추가한 후 웹 앱 에서 해당 데이터를 볼 수 있습니다.

UI 의 샘플 데이터

이제 DEK를 삭제 하면 어떻게 되는지 살펴보겠습니다. 샘플 앱 관리자 페이지에서 이 작업을 수행하며, 이 페이지는 키를 관리 할 권한 부여 있는 개인으로만 제한되어야 합니다.

샘플 앱 관리 페이지

'데이터 암호화 키 삭제' 옵션은 DEK를 제거하지만 사용자의 암호화됨 데이터는 그대로 유지합니다. 그 후에는 애플리케이션 에서 더 이상 데이터를 해독할 수 없습니다. 로그인한 사용자의 데이터를 조회 하려고 하면 오류가 발생합니다.

키 없이 암호화됨 데이터를 조회 하려고 할 때 표시되는 오류 메시지

참고

DEK를 삭제한 후에도 애플리케이션 최대 60 초 후 캐시 만료될 때까지 데이터를 해독하고 표시할 수 있습니다.

그러나 실제로 데이터베이스 에 남아 있는 것은 무엇입니까? 관리자 페이지로 돌아가서 Fetch data for all users을 클릭하여 정보를 검토 할 수 있습니다. 애플리케이션 이 데이터를 해독할 수 없는 경우 이 보기에서는 예외가 발생하지 않습니다. 대신 데이터베이스 에 저장된 내용을 정확히 표시합니다.

실제로 사용자 데이터를 삭제하지 않았더라도 데이터 암호화 키 더 이상 존재하지 않기 때문에 애플리케이션 암호화됨 필드 ' 사용자 이름' 및 'value'에 대한 암호 텍스트만 표시할 수 있습니다.

데모 앱 데이터베이스 의 원시 암호 텍스트

다음은 이 데이터를 가져오는 데 사용되는 코드입니다. 앞서 설명한 encrypt 메서드와 유사한 로직을 사용합니다. 애플리케이션 필터 없이 find 작업을 실행하여 모든 데이터를 조회 다음 ENCRYPTED_FIELDS 딕셔너리를 반복하여 필드를 해독합니다.

# flaskapp/db_queries.py
def fetch_all_data_unencrypted(decrypt=False):
results = list(app.data_collection.find())
if decrypt:
for field in ENCRYPTED_FIELDS.keys():
for result in results:
if result.get(field):
result[field], result["encryption_succeeded"] = decrypt_field(result[field])
return results

해독할 각 필드 에 대해 decrypt_field 함수가 호출되지만, 이 경우 애플리케이션 DEK 누락으로 인해 암호를 성공적으로 해독할 수 없는 경우 오류를 포착합니다.

# flaskapp/db_queries.py
# Try to decrypt a field, returning a tuple of (value, status). This will be
either (decrypted_value, True), or (raw_cipher_text, False) if we
couldn't decrypt
def decrypt_field(field):
try:
# We don't need to pass the DEK or algorithm to decrypt a field
field = app.mongodb_encryption_client.decrypt(field)
return field, True
# Catch this error in case the DEK doesn't exist.
except pymongo.errors.EncryptionError as ex:
if "not all keys requested were satisfied" in ex._message:
app.logger.warn(
"Decryption failed: could not find data encryption key to decrypt the record."
)
# If we can't decrypt due to missing DEK, return the "raw" value.
return field, False
raise ex

mongosh 셸 사용하여 데이터베이스 에서 직접 확인할 수 있는 항목이 없음을 증명할 수도 있습니다.

데이터베이스 쿼리 시 mongosh 셸 출력

이 점 에서도 사용자의 암호화됨 데이터는 여전히 존재합니다. 누군가 데이터베이스 백업 에서 암호화 키 복원하여 액세스 할 수 있습니다.

이를 방지하기 위해 샘플 애플리케이션 두 개의 개별 데이터베이스 클러스터를 사용합니다: 하나는 데이터 저장용이고 다른 하나는 DEK("키 볼트") 저장용입니다. 별도의 클러스터를 사용하면 애플리케이션 데이터와 키 볼트에 대한 백업 복원이 분리됩니다. 백업 에서 데이터 클러스터 복원해도 키 볼트 클러스터 에서 삭제된 DEK는 복원 않습니다.

클라이언트 측 필드 레벨 암호화 특정 데이터를 '잊는' 작업 간소화할 수 있습니다. 데이터 키를 삭제하면 다양한 데이터베이스, 컬렉션, 백업 및 로그에 존재하는 데이터를 효과적으로 삭제할 수 있습니다.

프로덕션 애플리케이션 에서는 암호화 키 제거하는 것 외에도 암호화됨 데이터 자체를 삭제 수도 있습니다. 이 '심층 방어' 접근 방식은 데이터가 실제로 분실되었는지 확인하는 데 도움이 됩니다. 데이터 삭제 외에도 암호화폐 파쇄를 구현하면 삭제 작업이 실패하거나 삭제되어야 하는 데이터가 포함되지 않을 경우의 영향 최소화할 수 있습니다.

돌아가기

KMIP로 자동 클라이언트 측 필드 레벨 암호화 사용

이 페이지의 내용