[Azure SQL]Using Always Encrypted with .NET (feat. Keyvault)(1)

데이터를 저장 및 관리 하다 보면, 민감한 정보를 아무나 볼 수 없도록 식별 불가능하게 하도록 비식별화 작업을 해야 할 때가 있다.

데이터 비식별화를 하는 방법은 여러가지가 있지만, 그 중에서 데이터를 암호화하는 방법을 Azure SQL의 Always Encrypted 기능을 사용해서 구현해보려고 한다.

Always Encryted 기능은 Azure SQL에 저장된 민감한 데이터를 암호화 시킬 수 있고, 암호화에 사용된 암호화 키를 DB engine과 공유하지 않기 때문에 권한이 있는 클라이언트만 실제 데이터를 확인 할 수 있다. 그래서 권한에 따라서 데이터를 볼 수 있는 사람과 없는 사람을 명확히 구분할 수 가 있게 된다.

구성 방법

Always Encryted 기능을 사용하기 위해서는 2가지 키가 필요하다.

  1. Column master key(CMK)
    • Column encryption key들을 암호화하는데 사용된다.
    • HSM 모듈을 사용해서 생성하고 Azure Keyvault에 저장한다.
  2. Column encrytion key(CEK)
    • Table의 특정 Column data를 암호화 하거나 복호화 하는데 사용된다.
    • 각 Column 별로 독립적으로 관리된다.

Create CMK

keyvault서비스에서 Key menu에서 Generate/Import 메뉴를 클릭한다.

사용할 RSA 키 정보를 입력하고 키를 생성한다.

  • Name: always-encryted-hsm
  • Key Type: RSA
  • Key Size: 3072

SQL Server Management Studio(SSMS)를 실행시킨다.
Object Explore에서 DB Instance를 선택하고, Security 폴더로 이동한다.
Always Encryted Key 폴더 밑에 Column master key폴더를 우클릭하여 master key 추가 메뉴를 클릭한다.

key store를 auzre keyvault를 선택하면, AAD Login을 해야한다. 정상적으로 로그인 하게 되면, subscription과 keyvault 리소스를 선택할 수 있다. 위에서 만든 RSA 키 정보를 찾아서 추가해준다.

여기까지 하면 Column master key가 생성된 것을 확인 할 수 있다.

Create CEK

이제 암호화를 대상이 되는 테이블을 우클릭 하면 Column Encryption key를 추가할 수 있는 메뉴를 확인 할 수 있다.

암호화를 해야 하는 Column들을 선택하고 위에서 만들 Master key를 사용해서 Column들을 암호화 한다.

이제 Table을 조회해 보면 해당 Column(email, name)의 정보가 식별할 수 없도록 암호화된 것을 확인 할 수 있다.

이 정보를 다시 복호화 하기 위해서는 SQL master 계정이나 Keyvault에 Cryptographic Operations 권한이 있는 계정을 사용해야 하며 Connection 정보에 “Column Encryption Setting = Enabled” 옵션을 추가해서 접근을 하면 복호화된 정보를 얻을 수 있다.

Next: [Azure SQL]Using Always Encrypted with .NET (feat. Keyvault)(2)

[Databricks] Using Azure Key Vault

Databricks에서 작업을 할 때 외부 데이터 소스를 가져와야 할 때가 있다. 이럴 때 외부 데이터 에 접근하기 위해서 연결 정보( ID, Password 등)가 필요하게 되는데, 이 정보는 작업자 외에 유출되면 안되는 경우가 있다.

이런 유출에 민감한 정보를 다뤄야 할 때, Secret manager 서비스를 사용하면 좋고, 이번 포스트에서는 Azure에서 제공하는 Key Vault 서비스를 사용해서 Databricks에서 민감정보를 다루는 방법을 알아보겠다.

먼저, Azure Key Vault 리소스를 생성하고 Secret에 연결 정보(SQL Connection string)를 등록한다.

이제 Databricks에서 Key Vault에 등록된 정보를 사용하기 위해서 secret scope를 만든다.

databricks secrets create-scope --scope databricks-secrets01 --scope-backend-type AZURE_KEYVAULT --resource-id /subscriptions/<subscription Id>/resourceGroups/<resource group name>/providers/Microsoft.KeyVault/vaults/databricks-secrets01 --dns-name https://databricks-secrets01.vault.azure.net/

잘 만들어 졌는지 아래 scope list 명령어로 확인해 본다.

databricks secrets list-scopes
Scope                 Backend         KeyVault URL
--------------------  --------------  ---------------------------------------------
databricks-secrets01  AZURE_KEYVAULT  https://databricks-secrets01.vault.azure.net/

이제 Databricks에서 Key Vault에 등록된 Secret 값을 사용하기 위한 준비 작업은 끝났다.
Workspace에서 notebook을 하나 만들고 아래 script 처럼 secret 값을 불러와 사용해보자.

jdbcUrl = dbutils.secrets.get(scope="databricks-secrets01", key="databricks-jdbc-url")
connectionProperties = {
  "user": dbutils.secrets.get(scope="databricks-secrets01", key="databricks-user"),
  "password": dbutils.secrets.get(scope="databricks-secrets01", key="databricks-password")
}

위 방식대로 불러온 값들은 변수에 저장되지만 databricks 내에서는 확인 할 수 없다.

값을 확인하기 위해서 print를 해보면 “REDACTED”라고 출력되는 것을 확인 할 수 있다.
하지만 해당 변수를 이용해서 실행시켜보면 정상 동작한다.

df = spark.read.jdbc(url=jdbcUrl, table='sys.objects', properties=connectionProperties)
df.show(2)

+----------+---------+------------+---------+----------------+----+------------+--------------------+--------------------+-------------+------------+-------------------+
|      name|object_id|principal_id|schema_id|parent_object_id|type|   type_desc|         create_date|         modify_date|is_ms_shipped|is_published|is_schema_published|
+----------+---------+------------+---------+----------------+----+------------+--------------------+--------------------+-------------+------------+-------------------+
| sysrscols|        3|        null|        4|               0|  S |SYSTEM_TABLE|2023-03-30 17:00:...|2023-03-30 17:00:...|         true|       false|              false|
|sysrowsets|        5|        null|        4|               0|  S |SYSTEM_TABLE|2009-04-13 12:59:...|2023-03-30 17:00:...|         true|       false|              false|
+----------+---------+------------+---------+----------------+----+------------+--------------------+--------------------+-------------+------------+-------------------+

이렇게 Azure Key Vault를 이용하면 Databricks에서 민감정보를 다뤄야 할 때, 실제 값을 보여주지 않으면서 script는 정상 동작 시킬 수 있다.

마지막으로, 사용하는 key vault에 있는 민감정보 값들이 더 이상 필요 없어진다면 해당 key vault에 접근 할 수 없도록 하는 것이 바람직하다. delete scope로 더 이상 사용 할 수 없도록 scope를 제거 할 수 있다.

 databricks secrets delete-scope --scope databricks-secrets01

Azure Key Vault 개요

일반적으로, Application Security를 하기위해 Key Vault를 적용하는 사례/방법은 아래와 같이 크게 4가지가 있다.

  1. General Secret Storage
    • 다양한 종류의 비밀들을 저장 할 수 있다.
      (예, 민감한 환경설정, 데이터베이스 크리덴셜, API 키 등)
    • Plan Text file,프로젝트 환경설정 관리, DB에 저장 등, 보통 사용되는 방식 보다 Vault Read나 Vault API를 사용하여 Query하는 것이 훨씬 안전하다.
    • Vault의 Audit Log를 통해서 접근들을 보호 할 수 있다.
  2. Employee Credential Storage
    • General Secret Storage의 확장되는 개념이다.
    • 웹 서비스에 접근하는 직원들의 인증 정보를 저장하기 좋다.
    • Audit Log를 통해서 어떤 직원이 비밀에 접근(및 작업) 했는지 쉽게 알 수 있다.
  3. API Key Generation for Scripts
    • 이상적인 Vault의 기능인 “Dynamic Secrets” 을 통해서 비밀에 접근하는 키를 일정 기간동안 생성하고 만료 시킬 수 있다.
    • Keypair는 스크립트 동작으로만 존재 하며, 키의 생성 작업은 완벽하게 로그로 남는다.
    • IAM(Identity Access Management) 사용 이상의 기술이지만, 때로는 하드코딩으로 접근 제한을 두는 것이더 효율 적일 수 있다.
  4. Data Encryption
    • Vault를 사용하여 비밀을 저장할 수있을뿐만 아니라 다른 곳에 저장된 데이터를 암호화/복호화 할 수 있다.
    • 이 것을 사용하면 응용 프로그램이 기본 데이터 저장소에 데이터를 저장하면서 데이터를 암호화를 할 수 있다.

Azure Key Vault와 같은 서비스는 Azure에만 있는 것은 아니고 대부분의 클라우드 서비스에서 데이터 암화에 대한 KMS(Key Management Service)를 제공하고 있다. 그러면 이러한 서비스이 어떤 차이 점이 있는지 알아보자

AWS KMS(Amazon Web Service Key Management Service)

  • 암호화 표준은 RSA-OAEP와 PKCS#1v1.5(현재 2.2까지 나왔음.)를 사용한다.
  • CMK(Customer Master Key)와 Data Key를 이용하여 데이터를 암호화 작업을 한다.
  1. CMK
    • 256-bit AES 키이며, 이 키는 내보낼 수 없다.
    • 키에 사용되는 대칭 알고리즘은 AES-GCM-256을 사용한다.
    • CMK를 사용하여 최대 4KB의 데이터를 암호화하고 해제 할 수 있다.
  2. Data Key
    • CMK를 사용하여 생성한다.
    • 많은 양의 데이터를 암호화 하는데 사용한다.

GCP KMS(Google Cloud Platform Key Management Service)

  • 암호화 표준은 RSA-OAEP와 AES-GCM을 사용한다.
  • 암호화 Key의 정확한 제어 엑세스 관리를 위해 Key ring, Key, Key version이라는 계층 구조를 가지고 있다.
  1. Key ring
    • 조직화 목적을 위해 키를 그룹화 한 것 이다.
    • Key는 Key를 포함하는 Key ring에서 권한을 상속받는다. 연관된 권한을 가진 Key를 Key ring으로 그룹화하면 각 키를 개벽적으로 작업을 수행할 필요 없이 Key ring 수준에서 해당 키를 대상으로 권한을 부여, 취소, 수정 할 수 있다.
  2. Key
    • AES-256키를 GCM(Galois Counter Mode)로 사용한다.
    • 특정한 용도를 위해 사용되는 암호화 키를 나타내는 명명된 객체이다.
    • 시간이 경과 되어 새로운 키 버전이 생성되면 키자료인 암호화에 사용되는 실제 비트가 변경될 수 있음.
  3. Key version
    • 일정한 시점에 하나의 키와 관련된 키 자료를 나타낸다.
    • 임의의 여러 버전이 존재 할 수 있으며 버전은 최소 하나 이상 있어야 한다.

Azure Key Vault

  • 암호화 표준은 RSA-OAEP를 사용한다.
  • 비밀정보를 중앙 위치에 보관하고 보안 액세스, 권한 제어 및 액세스 로깅을 제공한다.
  • 비밀 정보를 접근하고 사용하려면 Key Vault에 인증 해야하며, Key Vault 인증은 AAD(Azure Active Directory)에서 인증 지원하는 ID(App Client ID)를 통해 인증 받을 수 있다.
    • 접근 정책은 ‘작업’을 기반으로 한다.
      – Application 별로 비밀 값 읽기, 비밀 이름 나열, 비밀 만들기 등의 권한을 부여한다.
  • 제공되는 보안 컨트롤
    • Data Protect
      – TDE(투명한 데이터 암호화)와 Azure Key Vault를 통합하면 TDE 보호기라는 고객 관리형 비대칭 키를 사용하여 DEK(데이터베이스 암호화 키)를 암호화할 수 있습니다.
    • Network ACL
      – 가상 네트워크 서비스 End-Point를 사용하면 지정된 가상 네트워크에 대한 액세스를 제한할 수 있습니다.

정리하면, AWS, GCP의 KMS는 암호화 키를 안전하게 저장 하는 것과 키를 암호화하는 작업(암호화와 복호화)에  초점이 맞춰져 있다고 볼 수 있고, 반면, Azure Key Vault는 백엔드에서는 키 암호화 작업을 통해 비밀을 저장하는 등, KMS와 유사하게 기능들을 제공하지만 그 외 추가 적인 관리 기능들을 제공하기 때문에 비밀 관리 솔루션을 제공한다고 볼 수 있다.