Azure AI 검색에서 데이터 암호화를 위한 고객 관리형 키 구성

Azure AI 검색은 서비스 관리형 키를 사용하여 미사용 데이터를 자동으로 암호화합니다. 보호가 더 필요하면 Azure Key Vault에서 만들고 관리하는 키를 사용하여 다른 암호화 계층으로 기본 암호화를 보완할 수 있습니다.

이 문서에서는 CMK(고객 관리형 키) 또는 BYOK(사용자 고유 키) 암호화를 설정하는 단계를 안내합니다.

참고 항목

인덱스가 CMK 암호화된 경우 검색 서비스가 키에 액세스할 수 있는 경우에만 액세스할 수 있습니다. 액세스 권한이 철회되면 인덱스를 사용할 수 없으며 인덱스가 삭제되거나 키에 대한 액세스가 복원될 때까지 서비스의 크기를 조정할 수 없습니다.

CMK 암호화 개체

CMK 암호화는 개별 개체에 적용됩니다. 검색 서비스 전반에 걸쳐 CMK가 필요한 경우 적용 정책을 설정합니다.

CMK 암호화는 개체가 만들어질 때 작동합니다. 이미 존재하는 개체는 암호화할 수 없습니다. CMK 암호화는 개체가 디스크에 저장될 때마다(장기 저장을 위한 미사용 데이터 또는 단기 저장을 위한 임시 데이터) 발생합니다. CMK를 사용하면 디스크가 암호화되지 않은 데이터를 볼 수 없습니다.

암호화할 수 있는 개체에는 인덱스, 동의어 목록, 인덱서, 데이터 원본 및 기술 세트가 포함됩니다. 암호화는 암호를 해독하는 데 계산 비용이 많이 들기 때문에 중요한 콘텐츠만 암호화됩니다.

암호화는 다음 콘텐츠에 대해 수행됩니다.

  • 인덱스 및 동의어 목록 내의 모든 콘텐츠입니다.

  • 인덱서, 데이터 원본, 기술 세트 및 벡터라이저의 중요한 콘텐츠입니다. 이 콘텐츠는 연결 문자열, 설명, ID, 키 및 사용자 입력을 저장하는 필드로만 구성됩니다. 예를 들어, 기술 세트에는 Azure AI 서비스 키가 있고 일부 기술은 사용자 지정 엔터티와 같은 사용자 입력을 허용합니다. 두 경우 모두 기술에 대한 키와 사용자 입력이 암호화됩니다. 외부 리소스(예: Azure 데이터 원본 또는 Azure OpenAI 모델)에 대한 모든 참조도 암호화됩니다.

완전 이중 암호화

CMK 암호화를 도입하면 콘텐츠를 두 번 암호화하게 됩니다. 이전 섹션에서 언급한 개체 및 필드의 경우 콘텐츠는 먼저 CMK로 암호화되고 두 번째로 Microsoft 관리형 키로 암호화됩니다. 콘텐츠는 장기 저장용 데이터 디스크와 단기 저장용 임시 디스크에서 이중으로 암호화됩니다.

CMK 암호화를 사용하도록 설정하면 인덱스 크기가 늘어나고 쿼리 성능이 저하됩니다. 현재까지 관찰한 결과에 따르면 실제 성능은 인덱스 정의 및 쿼리 유형에 따라 다르지만 쿼리 시간이 30~60% 증가하는 것으로 예상할 수 있습니다. 성능이 저하되므로 실제로 필요한 개체에서만 이 기능을 사용하도록 설정하는 것이 좋습니다.

이제 이중 암호화는 모든 지역에서 사용할 수 있지만 지원은 두 단계로 롤아웃되었습니다.

  • 첫 번째 출시는 2020년 8월 1일이었으며 아래에 나열된 5개 지역이 포함되었습니다. 다음 지역에서 만들어진 Search Service는 데이터 디스크용 CMK를 지원했지만 임시 디스크는 지원하지 않았습니다.

    • 미국 서부 2
    • 미국 동부
    • 미국 중남부
    • US Gov 버지니아
    • US Gov 애리조나
  • 2021년 5월 13일의 두 번째 출시에서는 임시 디스크에 대한 암호화와 확장된 CMK 암호화를 지원되는 모든 지역에 추가했습니다.

    첫 번째 롤아웃 중에 만들어진 서비스의 CMK를 사용 중이고 임시 디스크에 대한 CMK 암호화도 원하는 경우 선택한 지역에서 새 검색 서비스를 만들고 콘텐츠를 다시 배포해야 합니다. 서비스 생성 날짜를 확인하려면 서비스 만들기 날짜를 확인하는 방법을 참조하세요.

필수 조건

제한 사항

  • Azure Key Vault 관리형 HSM(하드웨어 보안 모델)을 지원하지 않습니다.

  • Azure Portal에서 암호화 키 추가를 지원하지 않습니다.

  • 구독 간 지원이 없습니다. Azure Key Vault 및 Azure AI Search는 동일한 구독에 있어야 합니다.

Key Vault 팁

Azure Key Vault 경우 PowerShell을 사용하여 Azure Key Vault 비밀을 설정하고 검색하는 기본 작업에 대해 알아보려면 이 빠른 시작을 살펴보세요.

Key Vault를 사용하기 위한 몇 가지 팁은 다음과 같습니다.

  • 필요한 만큼 Key Vault를 사용합니다. 관리형 키는 여러 Key Vault에 있을 수 있습니다. 검색 서비스에는 여러 개의 암호화된 개체가 있을 수 있으며, 각 개체는 서로 다른 고객 관리형 암호화 키로 암호화되어 여러 Key Vault에 저장됩니다.

  • 시스템 또는 사용자 관리 ID를 통해 연결하여 관리되는 키를 검색할 수 있도록 동일한 테넌트를 사용합니다. 이 동작을 수행하려면 두 서비스가 동일한 테넌트를 공유해야 합니다. 테넌트를 만드는 방법에 대한 자세한 내용은 새 테넌트 설정을 참조하세요.

  • 제거 보호일시 삭제를 사용하도록 설정합니다. 고객 관리형 키를 사용하는 암호화의 특성으로 인해 Azure 키 자격 증명 모음 키가 삭제되면 아무도 데이터를 검색할 수 없습니다. Key Vault 실수로 키 삭제로 인한 데이터 손실을 방지하려면 키 자격 증명 모음에 대해 일시 삭제 및 제거 보호를 사용하도록 설정해야 합니다. 일시 삭제는 기본적으로 사용하도록 설정되므로 의도적으로 사용하지 않도록 설정하는 경우에만 문제가 발생합니다. 제거 보호는 기본적으로 사용하도록 설정되지 않지만 Azure AI 검색의 고객 관리형 키 암호화에는 필요합니다.

  • 키 사용량을 모니터링할 수 있도록 키 자격 증명 모음에 대한 로깅 을 사용하도록 설정합니다.

  • 키 자동 회전을 사용하도록 설정하거나 키 자격 증명 모음 키 와 애플리케이션 비밀 및 등록을 일상적인 순환하는 동안 엄격한 절차를 따릅니다. 이전 암호 및 키를 삭제하기 전에 새 비밀 및 키를 사용하도록 모든 암호화된 콘텐츠를 항상 업데이트합니다. 이 단계를 수행하지 않은 경우 콘텐츠의 암호를 해독할 수 없습니다.

1단계: Key Vault에서 키 만들기

사용할 Azure Key Vault 키가 이미 있는 경우 키 생성을 건너뛰고 키 식별자를 수집합니다. 암호화된 개체를 만들 때 이 정보가 필요합니다.

키를 추가하기 전에 Key Vault 암호화 책임자 역할을 자신에게 할당했는지 확인합니다.

Azure AI Search 암호화는 2048, 3072 및 4096 크기의 RSA 키를 지원합니다. 지원되는 키 유형에 대한 자세한 내용은 키 정보를 참조하세요.

  1. Azure Portal에 로그인하고 키 자격 증명 모음 개요 페이지를 엽니다.

  2. 왼쪽에서 개체>키를 선택한 다음 생성/가져오기를 선택합니다.

  3. 만들기 창의 옵션 목록에서 생성을 선택하여 새 키를 만듭니다.

  4. 키의 이름을 입력하고 다른 키 속성에 대한 기본값을 적용합니다.

  5. 필요에 따라 자동 회전을 사용하도록 키 회전 정책을 설정합니다.

  6. 만들기를 선택하여 배포를 시작합니다.

  7. 키를 선택하고 현재 버전을 선택한 다음 키 식별자를 적어 둡니다. 키 값 Uri, 키 이름키 버전으로 구성됩니다. Azure AI 검색에서 암호화된 인덱스를 정의하려면 식별자가 필요합니다.

    새 키 자격 증명 모음 키 만들기

2단계: 보안 주체 만들기

런타임에 암호화 키에 대한 Azure AI Search 액세스를 설정하는 몇 가지 옵션이 있습니다. 가장 간단한 방법은 검색 서비스의 관리 ID를 사용하여 키를 검색하는 것입니다. 시스템 관리 ID 또는 사용자 관리 ID를 지정할 수 있습니다. 이렇게 하면 애플리케이션 등록 및 애플리케이션 비밀에 대한 단계를 생략할 수 있습니다. 또는 Microsoft Entra 애플리케이션을 만들고 등록하고 검색 서비스에서 요청에 애플리케이션 ID를 제공하도록 할 수 있습니다.

관리 ID를 사용하는 것이 좋습니다. 관리되는 ID를 사용하면 검색 서비스에서 코드에 자격 증명(ApplicationID 또는 ApplicationSecret)을 저장하지 않고 Azure Key Vault에 인증할 수 있습니다. 이러한 유형의 관리 ID 수명 주기는 검색 서비스의 수명 주기에 연결되며, 하나의 시스템 할당 관리 ID만 가질 수 있습니다. 관리 ID의 작동 방식에 대한 자세한 내용은 Azure 리소스의 관리 ID 개요를 참조하세요.

검색 서비스에 대해 시스템 할당 관리 ID를 사용하도록 설정합니다.

시스템 할당 관리 ID를 켜는 스크린샷.

3단계: 권한 부여

Azure Key Vault는 역할 기반 액세스 제어를 사용하여 권한 부여를 지원합니다. 키 자격 증명 모음 액세스 정책에 대해 이 방법을 사용하는 것이 좋습니다. 자세한 내용은 Azure 역할을 사용하여 Key Vault 키, 인증서 및 비밀에 대한 액세스 제공을 참조 하세요.

이 단계에서는 Key Vault Crypto Service 암호화 사용자 역할을 검색 서비스에 할당합니다. 로컬에서 테스트하는 경우 이 역할도 자신에게 할당합니다.

  1. Azure Portal에 로그인하고 키 자격 증명 모음을 찾습니다.

  2. 액세스 제어(IAM)를 선택하고 역할 할당 추가를 선택합니다.

  3. Key Vault Crypto Service 암호화 사용자를 선택한 다음, 다음을 선택합니다.

  4. 관리 ID를 선택하고 멤버를 선택한 다음 검색 서비스의 관리 ID를 선택합니다.

  5. 검토 + 할당을 선택합니다.

역할 할당이 작동할 때까지 몇 분 정도 기다립니다.

4단계: 콘텐츠 암호화

개체를 만들 때 암호화 키가 추가됩니다. 인덱스, 동의어 맵, 인덱서, 데이터 원본 또는 기술 집합에 고객 관리형 키를 추가하려면 REST API 검색 또는 Azure SDK를 사용하여 암호화를 사용하도록 설정된 개체를 만듭니다. Azure SDK를 사용하여 암호화를 추가하려면 이 문서의 Python 예제를 참조하세요.

  1. 만들기 API를 호출하여 encryptionKey 속성을 지정합니다.

  2. encryptionKey 구문을 개체 정의에 삽입합니다. 이 속성은 이름 및 설명과 동일한 수준의 첫 번째 수준 속성입니다. 동일한 자격 증명 모음, 키 및 버전을 사용하는 경우 동일한 encryptionKey 구문을 각 개체 정의에 붙여넣을 수 있습니다.

    첫 번째 예제에서는 관리 ID를 사용하여 연결하는 검색 서비스에 대한 encryptionKey를 보여 줍니다.

    {
      "encryptionKey": {
        "keyVaultUri": "<YOUR-KEY-VAULT-URI>",
        "keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
        "keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>"
      }
    }
    

    두 번째 예제에는 Microsoft Entra ID에 애플리케이션을 등록한 경우 필요한 accessCredentials가 포함됩니다.

    {
      "encryptionKey": {
        "keyVaultUri": "<YOUR-KEY-VAULT-URI>",
        "keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
        "keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>",
        "accessCredentials": {
          "applicationId": "<YOUR-APPLICATION-ID>",
          "applicationSecret": "<YOUR-APPLICATION-SECRET>"
        }
      }
    }
    
  3. 개체에서 GET을 실행하여 암호화 키가 있는지 확인합니다.

  4. 암호화된 인덱스 쿼리와 같은 작업을 수행하여 개체가 작동하는지 확인합니다.

검색 서비스에서 암호화된 개체를 생성하면 해당 유형의 다른 개체와 마찬가지로 사용할 수 있습니다. 암호화는 사용자와 개발자에게 투명하게 처리됩니다.

이러한 주요 자격 증명 모음 세부 정보는 비밀로 간주되지 않으며 Azure Portal의 관련 Azure Key Vault 페이지로 이동하여 쉽게 검색할 수 있습니다.

Important

Azure AI 검색의 암호화된 콘텐츠는 특정 버전의 특정 Azure Key Vault 키를 사용하도록 구성됩니다. 키 또는 버전을 변경하는 경우 이전 키를 삭제하기 전에 해당 개체를 사용하도록 개체를 업데이트해야 합니다. 이렇게 하지 않으면 개체를 사용할 수 없게 됩니다. 키를 분실하면 콘텐츠의 암호를 해독할 수 없습니다.

5단계: 암호화 테스트

암호화가 작동하는지 확인하려면 암호화 키를 해지하고 인덱스를 쿼리한 다음(사용할 수 없어야 함) 암호화 키를 복원합니다.

이 작업에 Azure Portal을 사용합니다.

  1. Azure Key Vault 페이지에서 개체>키를 선택합니다.

  2. 방금 만든 키를 선택한 다음 삭제를 선택합니다.

  3. Azure AI Search 페이지에서 검색 관리>인덱스를 선택합니다.

  4. 인덱스 및 검색 탐색기를 사용하여 쿼리를 실행합니다. 오류가 발생합니다.

  5. Azure Key Vault 개체>키 페이지로 돌아갑니다.

  6. 삭제된 키 관리를 선택합니다.

  7. 키를 선택한 다음 복구를 선택합니다.

  8. Azure AI Search에서 인덱스로 돌아가서 쿼리를 다시 실행합니다. 검색 결과가 표시됩니다. 즉각적인 결과가 표시되지 않으면 잠시 기다렸다가 다시 시도하세요.

CMK 규정 준수를 적용하는 정책 설정

Azure Policy는 조직 표준을 적용하고 대규모 규정 준수를 평가하는 데 도움이 됩니다. Azure AI 검색에는 선택적 서비스 전체 CMK 적용을 위한 기본 제공 정책이 있습니다.

이 섹션에서는 검색 서비스에 대한 CMK 표준을 정의하는 정책을 설정합니다. 그런 다음 이 정책을 적용하도록 Search Service를 설정합니다.

  1. 웹 브라우저에서 기본 제공 정책으로 이동합니다. 할당 선택

    기본 제공 CMK 정책 할당 스크린샷.

  2. 정책 범위를 설정합니다. 매개 변수 섹션에서 매개 변수만 표시...를 선택 취소하고 효과거부로 설정합니다.

    요청을 평가하는 동안 거부 정책 정의와 일치하는 요청은 비준수로 표시됩니다. 서비스의 표준이 CMK 암호화라고 가정할 때 "거부"는 CMK 암호화를 지정하지 않는 요청이 규정을 준수하지 않음을 의미합니다.

    기본 제공 CMK 정책 효과를 거부로 변경하는 스크린샷.

  3. 정책 만들기를 마칩니다.

  4. 서비스 수준에서 CMK 정책 적용을 사용하도록 설정하려면 서비스 - 업데이트 API를 호출합니다.

PATCH https://management.azure.com/subscriptions/<your-subscription-Id>/resourceGroups/<your-resource-group-name>/providers/Microsoft.Search/searchServices/<your-search-service-name>?api-version=2023-11-01

{
    "properties": {
        "encryptionWithCmk": {
            "enforcement": "Enabled"
        }
    }
}

암호화 키 회전 또는 업데이트

Azure Key Vault자동 회전 기능을 사용하는 것이 좋지만 키를 수동으로 회전할 수도 있습니다.

키 또는 해당 버전을 변경하는 경우 이전 값을 삭제하기 전에 먼저 키를 사용하는 모든 개체를 업데이트하여 새 값을 사용해야 합니다. 그렇지 않으면 개체의 암호를 해독할 수 없으므로 개체를 사용할 수 없게 됩니다.

  1. 인덱스 또는 동의어 맵에 사용되는 키를 확인합니다.

  2. 키 자격 증명 모음에 새 키를 만들지만 원래 키를 사용할 수 있는 상태로 둡니다.

  3. 인덱스 또는 동의어 맵의 encryptionKey 속성을 업데이트하여 새 값을 사용합니다. 원래 이 속성을 사용하여 만든 개체만 다른 값을 사용하도록 업데이트할 수 있습니다.

  4. 키 자격 증명 모음에서 이전 키를 사용하지 않도록 설정하거나 삭제합니다. 키 액세스를 모니터링하여 새 키가 사용되고 있는지 확인합니다.

성능상의 이유로 검색 서비스는 최대 몇 시간 동안 키를 캐시합니다. 새 키를 제공하지 않고 키를 사용하지 않도록 설정하거나 삭제한 경우에는 캐시가 만료될 때까지 쿼리가 일시적으로 계속 작동합니다. 그러나 검색 서비스에서 콘텐츠 암호를 더 이상 해독할 수 없는 경우 다음 메시지가 표시됩니다. "액세스가 금지되었습니다. 사용된 쿼리 키가 해지되었을 수 있습니다. 다시 시도하십시오."

암호화된 열로 작업

고객 관리형 키 암호화를 사용하여 추가 암호화/암호 해독 작업으로 인해 인덱싱 및 쿼리 모두에 대한 대기 시간을 확인할 수 있습니다. Azure AI 검색은 암호화 작업을 기록하지 않지만 키 자격 증명 모음 로깅을 통해 키 액세스를 모니터링할 수 있습니다.

키 자격 증명 모음 구성의 일부로 로깅을 사용하는 것이 좋습니다.

  1. 로그 분석 작업 영역 만들기.

  2. 데이터 보존을 위해 작업 영역을 사용하는 진단 설정을 키 자격 증명 모음에 추가합니다.

  3. 범주에 대한 감사 또는 allLogs를 선택하고 진단 설정에 이름을 지정한 다음 저장합니다.

암호화 키 구성의 Python 예제

이 섹션에서는 개체 정의의 encryptionKey Python 표현을 보여줍니다. 인덱스, 데이터 원본, 기술 세트, 인덱서 및 동의어 맵에도 동일한 정의가 적용됩니다. 검색 서비스 및 키 자격 증명 모음에서 이 예제를 시도하려면 azure-search-python-samples에서 Notebook을 다운로드합니다.

일부 패키지를 설치합니다.

! pip install python-dotenv
! pip install azure-core
! pip install azure-search-documents==11.5.1
! pip install azure-identity

암호화 키가 있는 인덱스 만들기

from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents.indexes.models import (
    SimpleField,
    SearchFieldDataType,
    SearchableField,
    SearchIndex,
    SearchResourceEncryptionKey
)
from azure.identity import DefaultAzureCredential

endpoint="<PUT YOUR AZURE SEARCH SERVICE ENDPOINT HERE>"
credential = DefaultAzureCredential()

index_name = "test-cmk-index"
index_client = SearchIndexClient(endpoint=endpoint, credential=credential)  
fields = [
        SimpleField(name="Id", type=SearchFieldDataType.String, key=True),
        SearchableField(name="Description", type=SearchFieldDataType.String)
    ]

scoring_profiles = []
suggester = []
encryption_key = SearchResourceEncryptionKey(
    key_name="<PUT YOUR KEY VAULT NAME HERE>",
    key_version="<PUT YOUR ALPHANUMERIC KEY VERSION HERE>",
    vault_uri="<PUT YOUR KEY VAULT ENDPOINT HERE>"
)

index = SearchIndex(name=index_name, fields=fields, encryption_key=encryption_key)
result = index_client.create_or_update_index(index)
print(f' {result.name} created')

인덱스 정의를 가져와서 암호화 키 구성이 있는지 확인합니다.

index_name = "test-cmk-index-qs"
index_client = SearchIndexClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)  

result = index_client.get_index(index_name)  
print(f"{result}")  

몇 가지 문서를 사용하여 인덱스 로드 모든 필드 콘텐츠는 중요한 것으로 간주되며 고객 관리형 키를 사용하여 디스크에서 암호화됩니다.

from azure.search.documents import SearchClient

# Create a documents payload
documents = [
    {
    "@search.action": "upload",
    "Id": "1",
    "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities."
    },
    {
    "@search.action": "upload",
    "Id": "2",
    "Description": "The hotel is situated in a  nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts."
    },
    {
    "@search.action": "upload",
    "Id": "3",
    "Description": "The hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services."
    },
    {
    "@search.action": "upload",
    "Id": "4",
    "Description": "The hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace."
    }
]

search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, index_name=index_name, credential=credential)
try:
    result = search_client.upload_documents(documents=documents)
    print("Upload of new document succeeded: {}".format(result[0].succeeded))
except Exception as ex:
    print (ex.message)

    index_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)

쿼리를 실행하여 인덱스가 작동하는지 확인합니다.

from azure.search.documents import SearchClient

query = "historic"  

search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential, index_name=index_name)
  
results = search_client.search(  
    query_type='simple',
    search_text=query, 
    select=["Id", "Description"],
    include_total_count=True
    )
  
for result in results:  
    print(f"Score: {result['@search.score']}")
    print(f"Id: {result['Id']}")
    print(f"Description: {result['Description']}")

쿼리의 출력은 다음 예제와 유사한 결과를 생성해야 합니다.

Score: 0.6130029
Id: 4
Description: The hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.
Score: 0.26286605
Id: 1
Description: The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.

암호화된 콘텐츠는 데이터 새로 고침 또는 쿼리 전에 암호가 해독되므로 암호화에 대한 시각적 증거가 표시되지 않습니다. 암호화가 작동하는지 확인하려면 리소스 로그를 확인합니다.

다음 단계

Azure 보안 아키텍처에 익숙하지 않은 경우 Azure 보안 설명서, 특히 이 문서를 검토합니다.