# Python 디택션 작성하기

## 개요

Panther Console 또는 로컬에서 다음을 따라 자체 Python 디택션을 작성할 수 있습니다 [CLI 워크플로](/ko/panther/detections-repo/ci-cd.md). Python 디택션을 작성할 때는 [이 모범 사례를](#python-detection-writing-best-practices), 그리고 [일부 알러트 필드는 동적으로 설정할 수 있다는 점을 기억하세요](#alert-functions-in-python-detections). Python으로 작성된 룰은 [디택션 파생](/ko/detections/rules/derived.md).

대신 다음을 사용할 수도 있습니다 [코드 없는 디택션 빌더](/ko/detections/rules/simple-detection-builder.md) 를 Console에서 사용하여 룰을 만들거나, [로컬에서 Simple Detections로 작성할 수 있습니다](/ko/detections/rules/writing-simple-detections.md). 디택션을 로컬에서 Simple Detections로 작성할지 Python 디택션으로 작성할지 확실하지 않다면, 다음을 참조하세요 [Python과 간단한 디택션 YAML 사용](https://docs.panther.com/ko/detections/rules/pages/03a99462193d3cb6f09cb46a6d9fa32a7a6035d0#using-python-vs.-simple-detections-yaml) 섹션.

{% hint style="info" %}
새 Python 디택션을 작성하기 전에, 다음이 있는지 확인하세요 [Panther에서 관리하는 디택션](/ko/detections/panther-managed.md) 이(가) 요구 사항을 충족하는지(또는 *거의* 요구 사항을 충족하는지—Panther에서 관리하는 룰은 다음을 통해 조정할 수 있습니다 [인라인 필터](/ko/detections/rules/inline-filters.md)). Panther에서 관리하는 디택션을 활용하면 직접 작성하는 수고를 덜 수 있을 뿐 아니라, Panther가 새 버전을 출시할 때 핵심 디택션 로직에 대한 지속적인 업데이트 혜택도 받을 수 있습니다.
{% endhint %}

{% hint style="warning" %}
Panther의 디택션 내에서 외부 API 요청을 만드는 것은 매우 권장되지 않습니다. 일반적으로 디택션은 매우 큰 규모로 처리되며, API 요청을 생성하면 수신 시스템에 과부하가 걸리고 룰이 다음 한도를 초과할 수 있습니다 [15초 실행 시간 제한](/ko/detections/rules.md#rule-errors-and-scheduled-rule-errors).
{% endhint %}

## Python에서 디택션을 만드는 방법

### Python에서 룰을 만드는 방법

Panther Console과 CLI 워크플로 모두에서 Python 룰을 작성할 수 있습니다.

<details>

<summary>Console에서 Python으로 룰 만들기</summary>

1. Panther Console의 왼쪽 탐색 표시줄에서 **디택션**.
2. 을 클릭합니다 **새로 만들기**.
3. 에서 **Python 룰** 타일을 클릭하세요 **시작**.
4. 생성 페이지에서 룰을 구성하세요:
   * **Name**: 룰에 대한 설명이 포함된 이름을 입력하세요.
   * **ID** (선택 사항)**:** 펜 아이콘을 클릭하고 룰에 대한 고유 ID를 입력하세요.
   * 오른쪽 상단 모서리에서 **활성화됨** 토글은 기본적으로 `ON` 로 설정됩니다. 룰을 비활성화하려면 토글을 `OFF`.
   * 에서 **다음 소스에 대해** 섹션:
     * **로그 유형**: 이 룰이 적용되어야 하는 로그 유형을 선택하세요.
   * 에서 **디텍션** 섹션:
     * 에서 **룰 함수** 텍스트 편집기에서 Python `룰` 함수를 작성하여 디택션을 정의하세요.
       * 디택션 템플릿과 예시는 다음을 참조하세요 [panther\_analysis GitHub 저장소](https://github.com/panther-labs/panther-analysis/tree/master/templates).
   * 에서 **알러트 생성** 섹션에서 다음을 설정하세요 **알러트 생성** `ON/OFF` 토글. 이는 일치 항목이 있을 때 [알러트](/ko/alerts.md) 가 생성되어야 하는지, 아니면 [Signal](/ko/detections/signals.md)만 생성되어야 하는지를 나타냅니다. 이 토글을 `ON`:
     * **심각도**: 다음을 선택하세요 [심각도 수준](#alert-severity) 이 디택션으로 트리거되는 알러트에 대한
     * 에서 **선택적 필드** 섹션에서 다음 필드의 값을 선택적으로 입력하세요:
       * **설명**: 룰에 대한 추가 컨텍스트를 입력하세요.
       * **런북**: 이 룰과 관련된 절차 및 작업을 입력하세요.
         * 다음에서 자세히 알아보기 [알러트 실행 가이드](/ko/alerts/alert-runbooks.md).
         * 설명적인 실행 가이드를 제공하는 것이 권장됩니다, 왜냐하면 [Panther AI 알러트 분류](/ko/alerts.md#panther-ai-alert-triage) 이를 고려할 것이기 때문입니다.
       * **Reference**: 이 룰과 관련된 추가 정보를 위한 외부 링크를 입력하세요.
       * **대상 재정의:** 심각도와 관계없이 이 디택션에 대한 알러트를 수신할 대상지를 선택하세요. 대상지는 룰 함수에서 동적으로 설정할 수도 있습니다. 자세한 내용은 [라우팅 순서 우선순위](/ko/alerts/destinations.md#routing-order-precedence) 를 참조하세요.
       * **중복 제거 기간** Run Panther AI **이벤트 임계값**: 룰 일치에 대한 중복 제거 기간과 임계값을 입력하세요. 중복 제거가 작동하는 방식을 알아보려면 [중복 제거](#deduplication).
       * **요약 속성**: 이 디택션에 의해 트리거되는 알러트에서 표시할 속성을 입력하세요.
         * 중첩된 필드를 요약 속성으로 사용하려면, Summary Attribute 필드에서 Snowflake 점 표기법을 사용하여 JSON 객체의 경로를 탐색하세요:

           `<column>:<level1_element>.<level2_element>.<level3_element>`

           그러면 알러트 요약이 알러트 내에서 참조된 객체에 대해 생성됩니다. [Snowflake에서 반구조화된 데이터를 탐색하는 방법에 대해 자세히 알아보려면 여기를 참조하세요.](https://docs.snowflake.com/en/user-guide/querying-semistructured.html#label-traversing-semistructured-data)
         * 알러트 요약에 대한 자세한 내용은 [알러트 할당 및 관리](/ko/alerts/alert-management.md).
       * **사용자 지정 태그**: 이 룰을 한눈에 이해하는 데 도움이 되도록 사용자 지정 태그를 입력하세요(예: `HIPAA`.)
       * 에서 **프레임워크 매핑** 섹션:
         1. 을 클릭합니다 **새로 추가** 을 입력하세요.
         2. 다음 필드의 값을 입력하세요:
            * **보고서 키**: 보고서와 관련된 키를 입력하세요.
            * **보고서 값**: 해당 보고서의 값을 입력하세요.
   * 에서 **테스트** 섹션:
     * 에서 **단위 테스트** 섹션에서 **새로 추가** 을 [테스트 생성](/ko/detections/testing.md) 을 클릭하여 이전 단계에서 정의한 룰에 대한 테스트를 생성하세요.
5. 오른쪽 상단에서 다음을 클릭합니다 **저장**.

룰을 생성한 후에는 다음을 사용하여 수정할 수 있습니다 [인라인 필터](/ko/detections/rules/inline-filters.md).

</details>

<details>

<summary>CLI 워크플로에서 Python으로 룰 생성하기</summary>

로컬에서 디택션을 작성하는 경우(Panther Console이 아닌 경우), GitHub 또는 GitLab 같은 버전 관리 시스템에서 로컬 디택션 파일을 관리하는 것을 권장합니다.

사용자 지정 디택션 콘텐츠는 다음 중 하나를 생성하여 시작하는 것이 좋습니다 [공개 포크](https://docs.panther.com/panther-developer-workflows/ci-cd/detections-repo/public-fork) 또는 [비공개 복제 저장소](https://docs.panther.com/panther-developer-workflows/ci-cd/detections-repo/private-cloned-repo) Panther의 [오픈 소스 panther-analysis 저장소](https://github.com/panther-labs/panther-analysis).

**폴더 설정**

룰을 폴더로 그룹화하는 경우, 각 폴더 이름에는 반드시 다음이 포함되어야 합니다. `룰` 업로드 중(PAT 또는 Console의 대량 업로더 사용) 이를 찾을 수 있도록 하기 위해서입니다.

로그/리소스 유형을 기준으로 룰을 폴더로 그룹화하는 것을 권장합니다. 예: `suricata_rules` 또는 `aws_s3_policies`. 다음을 [panther-analysis](https://github.com/panther-labs/panther-analysis) 저장소를 참고 자료로 사용할 수 있습니다.

**파일 설정**

각 룰 및 예약된 룰은 다음으로 구성됩니다:

* 디택션 로직이 포함된 Python 파일(Python 파일, 즉 `.py` 확장자를 가진 파일).
* YAML 사양 파일(다음 확장자를 가진 파일 `.yml` 디택션의 메타데이터 속성을 포함하는 extension)입니다.
  * 관례적으로, 이 파일에는 Python 파일과 동일한 이름을 부여합니다.

Rules는 수상한 동작을 디텍트하기 위한 Python 함수입니다. 값을 반환하는 것은 `참` 의심스러운 활동을 나타내며, 이는 알러트를 트리거합니다.

1. 룰을 작성하고 (원하는 폴더에) my\_new\_룰.py로 저장하세요. `my_new_룰.py`:

   ```python
   def 룰(event):  
     return 'prod' in event.get('hostName')
   ```
2. 아래 템플릿을 사용하여 메타데이터 파일을 생성하세요:

   ```yaml
   AnalysisType: 룰
   DedupPeriodMinutes: 60 # 1시간
   표시 이름: 형식 확인용 예제 룰
   활성화됨: true
   파일 이름: my_new_룰.py
   룰ID: Type.Behavior.MoreContext
   심각도: 높음
   로그 유형:
     - LogType.GoesHere
   보고서:
     보고서 이름(예: CIS, MITRE ATT&CK):
       - 이 룰과 관련된 특정 보고서 섹션
   태그:
     - 태그
     - Go
     - 여기
   설명: >
     이 룰은 Panther CLI의 CLI 워크플로를 검증하기 위해 존재합니다
   런북: >
     먼저, 이 스펙 형식을 작성한 사람이 누구인지 알아낸 다음, 피드백과 함께 그들에게 알려주세요.
   참조: https://www.a-clickable-link-to-more-info.com
   ```

이 룰이 업로드되면, 일반적으로 Panther Console에서 입력하는 각 필드가 자동으로 채워집니다. 다음을 참조하세요 [룰 사양 참조](#python-rule-specification-reference) 필수 및 선택 필드의 전체 목록은

</details>

### Python에서 스케줄된 룰을 만드는 방법

Panther Console과 CLI 워크플로 둘 다에서 Python 스케줄된 룰을 작성할 수 있습니다.

<details>

<summary>Console에서 Python으로 스케줄된 룰 만들기</summary>

1. Panther Console의 왼쪽 탐색 표시줄에서 **디택션**.
2. 을 클릭합니다 **새로 만들기**.
3. 에서 **스케줄된 룰** 타일을 클릭하세요 **시작**.
4. 생성 페이지에서 스케줄된 룰을 구성하세요:
   * **Name**: 스케줄된 룰의 설명적인 이름을 입력합니다.
   * **ID** (선택 사항)**:** 펜 아이콘을 클릭하고 스케줄된 룰에 대한 고유 ID를 입력합니다.
   * 오른쪽 상단 모서리에서 **활성화됨** 토글은 기본적으로 `ON` 기본적으로. 스케줄된 룰을 비활성화하려면 토글을 `OFF`.
   * 에서 **다음 예약 쿼리에 대해** 섹션:
     * **예약 쿼리**: API 키에 대해 하나 이상의 [예약 검색](/ko/search/scheduled-searches.md) 이 예약 룰이 적용되어야 합니다.
   * 에서 **디텍션** 섹션:
     * 에서 **룰 함수** 텍스트 편집기에서 Python `룰` 함수를 작성하여 디택션을 정의하세요.
       * 모든 필터링 로직이 이미 관련 [예약 쿼리](/ko/search/scheduled-searches.md)의 SQL에서 처리되어 있다면, `룰` 함수를 단순히 반환하도록 구성할 수 있습니다 `true` 각 행에 대해:

         ```python
         def 룰(event):  
             True를 반환
         ```
       * 디택션 템플릿과 예시는 다음을 참조하세요 [panther\_analysis GitHub 저장소](https://github.com/panther-labs/panther-analysis/tree/master/templates)
   * 에서 **알러트 생성** 섹션에서 다음을 설정하세요 **알러트 생성** `ON/OFF` 토글. 이는 일치 항목이 있을 때 [알러트](/ko/alerts.md) 가 생성되어야 하는지, 아니면 [Signal](/ko/detections/signals.md)만 생성되어야 하는지를 나타냅니다. 이 토글을 `ON`:
     * **심각도**: 다음을 선택하세요 [심각도 수준](#alert-severity) 이 디택션으로 트리거되는 알러트에 대한
     * 에서 **선택적 필드** 섹션에서 다음 필드의 값을 선택적으로 입력하세요:
       * **설명**: 룰에 대한 추가 컨텍스트를 입력하세요.
       * **런북**: 이 룰과 관련된 절차 및 작업을 입력하세요.
         * 다음에서 자세히 알아보기 [알러트 실행 가이드](/ko/alerts/alert-runbooks.md).
         * 설명적인 실행 가이드를 제공하는 것이 권장됩니다, 왜냐하면 [Panther AI 알러트 분류](/ko/alerts.md#panther-ai-alert-triage) 이를 고려할 것이기 때문입니다.
       * **Reference**: 이 룰과 관련된 추가 정보를 위한 외부 링크를 입력하세요.
       * **대상 재정의:** 심각도와 관계없이 이 디택션에 대한 알러트를 수신할 대상지를 선택하세요. 대상지는 룰 함수에서 동적으로 설정할 수도 있습니다. 자세한 내용은 [라우팅 순서 우선순위](/ko/alerts/destinations.md#routing-order-precedence) 를 참조하세요.
       * **중복 제거 기간** Run Panther AI **이벤트 임계값**: 룰 일치에 대한 중복 제거 기간과 임계값을 입력하세요. 중복 제거가 작동하는 방식을 알아보려면 [중복 제거](#deduplication).
       * **요약 속성**: 이 디택션에 의해 트리거되는 알러트에서 표시할 속성을 입력하세요.
         * 중첩된 필드를 요약 속성으로 사용하려면, Summary Attribute 필드에서 Snowflake 점 표기법을 사용하여 JSON 객체의 경로를 탐색하세요:

           `<column>:<level1_element>.<level2_element>.<level3_element>`

           그러면 알러트 요약이 알러트 내에서 참조된 객체에 대해 생성됩니다. [Snowflake에서 반구조화된 데이터를 탐색하는 방법에 대해 자세히 알아보려면 여기를 참조하세요.](https://docs.snowflake.com/en/user-guide/querying-semistructured.html#label-traversing-semistructured-data)
         * 알러트 요약에 대한 자세한 내용은 [알러트 할당 및 관리](/ko/alerts/alert-management.md).
       * **사용자 지정 태그**: 이 룰을 한눈에 이해하는 데 도움이 되도록 사용자 지정 태그를 입력하세요(예: `HIPAA`.)
       * 에서 **프레임워크 매핑** 섹션:
         1. 을 클릭합니다 **새로 추가** 을 입력하세요.
         2. 다음 필드의 값을 입력하세요:
            * **보고서 키**: 보고서와 관련된 키를 입력하세요.
            * **보고서 값**: 해당 보고서의 값을 입력하세요.
   * 에서 **테스트** 섹션:
     * 에서 **단위 테스트** 섹션에서 **새로 추가** 을 [테스트 생성](/ko/detections/testing.md) 을 클릭하여 이전 단계에서 정의한 룰에 대한 테스트를 생성하세요.
5. 오른쪽 상단에서 다음을 클릭합니다 **저장**.
   * 클릭하면 **저장**가 활성화됩니다. 연결된 항목에서 반환된 SQL은 [예약 쿼리](/ko/search/scheduled-searches.md) (쿼리에서 정의된 간격으로) 스케줄된 룰을 통해 실행됩니다(단, 행이 반환되는 경우에 한함).

룰을 생성한 후에는 다음을 사용하여 수정할 수 있습니다 [인라인 필터](/ko/detections/rules/inline-filters.md).

</details>

<details>

<summary>CLI 워크플로에서 Python으로 스케줄된 룰 만들기</summary>

로컬에서 디택션을 작성하는 경우(Panther Console이 아닌 경우), GitHub 또는 GitLab 같은 버전 관리 시스템에서 로컬 디택션 파일을 관리하는 것을 권장합니다.

사용자 지정 디택션 콘텐츠는 다음 중 하나를 생성하여 시작하는 것이 좋습니다 [공개 포크](https://docs.panther.com/panther-developer-workflows/ci-cd/detections-repo/public-fork) 또는 [비공개 복제 저장소](https://docs.panther.com/panther-developer-workflows/ci-cd/detections-repo/private-cloned-repo) Panther의 [오픈 소스 panther-analysis 저장소](https://github.com/panther-labs/panther-analysis).

**폴더 설정**

룰을 폴더로 그룹화하는 경우, 각 폴더 이름에는 문자열 `룰` 업로드 중(PAT 또는 Console의 대량 업로더 사용) 이를 찾을 수 있도록 하기 위해서입니다.

로그/리소스 유형을 기준으로 룰을 폴더로 그룹화하는 것을 권장합니다. 예: `suricata_rules` 또는 `aws_s3_policies`. 다음을 [panther-analysis](https://github.com/panther-labs/panther-analysis) 저장소를 참고 자료로 사용할 수 있습니다.

**파일 설정**

각 스케줄된 룰은 다음으로 구성됩니다:

* 디택션 로직이 포함된 Python 파일(Python 파일, 즉 `.py` 확장자를 가진 파일).
* YAML 사양 파일(다음 확장자를 가진 파일 `.yml` 디택션의 메타데이터 속성을 포함하는 extension)입니다.
  * 관례적으로, 이 파일에는 Python 파일과 동일한 이름을 부여합니다.

스케줄된 룰을 사용하면 다음의 출력 결과를 분석할 수 있습니다: [스케줄된 검색](/ko/search/scheduled-searches.md) Python으로. 값이 반환되면 `참` 의심스러운 활동을 나타내며, 이는 알러트를 트리거합니다.

1. 쿼리를 작성하고 다음으로 저장하세요 `my_new_scheduled_query.yml`:

   ```yaml
   AnalysisType: scheduled_query
   QueryName: 내 새 예약 쿼리 이름
   활성화됨: true
   태그:
     - 선택 사항
     - 태그
   설명: >
     선택적 설명
   Query: 'SELECT * FROM panther_logs.aws_cloudtrail LIMIT 10'
   Schedule:
     # 참고: CronExpression과 RateMinutes는 상호 배타적이며, 하나만
     # 설정하세요
     CronExpression: '0 * * * *'
     평가 분: 1
     타임아웃 분: 1
   ```
2. 룰을 작성하고 다음 이름으로 저장하세요 `my_new_룰.py`:

   ```python
   # 참고: 더 많은 옵션은 예시 룰을 참조하세요
   # https://github.com/panther-labs/panther-analysis/blob/master/templates/example_룰.py

   def 룰(_):
       # 참고: 여기에서 추가 로직을 추가할 수 있습니다
       True를 반환
   ```
3. 메타데이터 파일을 만들고 다음 이름으로 저장합니다 `my_new_schedule_룰.yml`:

   ```yaml
   분석유형: scheduled_룰
   파일 이름: my_new_룰.py 
   룰ID: My.New.룰
   표시 이름: 더 친숙한 이름
   활성화됨: true
   예약된 쿼리:
     - 내 새 예약 쿼리 이름
   태그:
     - 태그
   심각도: 중간
   설명: >
     선택적 설명
   런북: >
     선택 사항인 런북 
   참조: 선택 사항인 reference.link 
   Tests:
     -
       이름: 이름 
       예상 결과: true
       로그:
         {
           "JSON": "string"
         }
   ```

이 스케줄된 룰이 업로드되면, 각 파일은 스케줄된 쿼리와 룰을 연결하고, 일반적으로 Panther Console에서 입력하는 필드가 자동으로 채워집니다. 참조 [아래의 룰 사양 참조](#python-rule-specification-reference) 필수 및 선택 필드의 전체 목록은

</details>

### Python에서 정책을 만드는 방법

* 정책을 만드는 방법을 알아보려면 다음을 참조하세요. [정책에서 정책 작성 방법 안내](/ko/detections/policies.md#how-to-write-a-policy).

## Python 디택션 구문

로컬 Python 디택션은 두 개의 파일로 구성됩니다: Python 파일과 YAML 파일입니다. Panther Console에서 Python 디택션을 만들 때는 Python 텍스트 편집기만 있고(YAML 편집기는 없음), 아래 YAML 열에 나열된 키들은 사용자 인터페이스의 필드에 설정됩니다.

<table data-full-width="false"><thead><tr><th>Python 파일에는 다음이 포함될 수 있습니다:</th><th>YAML 파일에는 다음이 포함될 수 있습니다:</th></tr></thead><tbody><tr><td><ul><li><p>디택션 로직</p><pre class="language-python"><code class="lang-python">def 룰(event): # 또는 def policy(resource):
</code></pre></li><li><p>알러트 함수(동적)</p><pre class="language-python"><code class="lang-python">def severity(event):
def title(event):
def dedup(event):
def unique(event):
def destinations(event):
def runbook(event):
def reference(event):
def description(event):
def 알러트_context(event):
</code></pre></li></ul></td><td><ul><li><p>필터 키</p><pre class="language-yaml"><code class="lang-yaml">InlineFilters: 
</code></pre></li><li><p>메타데이터 키</p><pre class="language-yaml"><code class="lang-yaml">AnalysisType: # 룰, scheduled_룰, 또는 정책
Enabled: 
FileName: 
CreatedBy:
RuleID: # 또는 PolicyId:
로그 유형: 
보고서: 
태그: 
Tests: 
ScheduledQueries: # scheduled 룰에만 적용됨
Suppressions: # 정책에만 적용됨
CreateAlert: # 정책에는 적용되지 않음
</code></pre></li><li><p>알러트 키 (정적)</p><pre class="language-yaml"><code class="lang-yaml">Severity:
Description:
DedupPeriodMinutes:
임계값: 
표시 이름:
출력 ID:
참조:
Runbook:
요약 속성: 
</code></pre></li></ul></td></tr></tbody></table>

### **기본 Python 룰 구조**

오직 하나의 `룰()` 함수와 아래에 표시된 YAML 키만 Python 룰에 필요합니다. 그러나 추가 Python 알러트 함수는 알러트를 더 동적으로 만들 수 있습니다. 추가 YAML 키도 사용할 수 있습니다. 자세한 내용은 [Python 룰 사양 참조](#python-rule-specification-reference).

<table><thead><tr><th>룰.py</th><th>룰.yml</th></tr></thead><tbody><tr><td><pre class="language-python"><code class="lang-python">def 룰(event): 
    if event.get("Something"): 
        True를 반환 
    return False
</code></pre></td><td><pre class="language-yaml"><code class="lang-yaml">AnalysisType: 룰
활성화됨: true
파일 이름: 룰.py
룰ID: my.룰
로그 유형: 
    - Some.Schema
심각도: INFO
</code></pre></td></tr></tbody></table>

더 많은 템플릿은 다음을 참조하세요: [GitHub의 panther-analysis 저장소](https://github.com/panther-labs/panther-analysis/tree/master/templates).

### `인라인 필터`

사용 방법에 대해 자세히 알아보기 `인라인 필터` Python 규칙에서 [인라인 필터로 디택션 수정하기](/ko/detections/rules/inline-filters.md#creating-filters-in-the-developer-workflow).

### Python 디택션의 알러트 함수

Panther의 디택션 보조 함수는 분석 로직, 생성된 알러트 제목, 이벤트 그룹화, 알러트 라우팅 및 메타데이터 재정의를 제어하는 Python 함수입니다. 규칙은 사용자 지정이 가능하며 표준 Python 라이브러리 또는 [전역 헬퍼](/ko/detections/rules/python/globals.md).

규칙과 정책 모두에 적용되며, 아래 각 함수는 다음의 단일 인수를 받습니다. `이벤트` (rules) 또는 `resource` (정책). 고급 사용자는 아래에 정의된 함수 외부에 함수, 변수 또는 클래스를 정의할 수 있습니다.

사용 중이라면 [알러트 중복 제거](/ko/detections/rules.md#deduplication-of-alerts)로 설정되면 *첫 번째* 디택션과 일치하는 이벤트는 이러한 알러트 함수의 매개변수로 사용됩니다.

아래의 각 알러트 함수는 선택 사항이지만, 알러트에 동적 컨텍스트를 추가할 수 있습니다.

<table data-full-width="false"><thead><tr><th width="182.2">알러트 함수</th><th width="307">설명</th><th width="417">기본값</th><th width="399">반환값</th></tr></thead><tbody><tr><td><a href="#severity"><code>심각도</code></a></td><td>알러트의 긴급 수준</td><td><p>YAML에서는: <code>심각도</code> 키</p><hr><p>콘솔에서는: <strong>심각도</strong> 필드</p></td><td><code>정보</code>, <code>낮음</code>, <code>보통</code>, <code>높음</code>,<code>치명적</code>, 또는 <code>기본값</code></td></tr><tr><td><a href="#title"><code>제목</code></a></td><td>생성된 알러트 제목</td><td><p>YAML에서는: <code>DisplayName</code> > <code>RuleID</code> 또는 <code>PolicyID</code></p><hr><p>콘솔에서는: <strong>Name</strong> 필드 > <strong>ID</strong> 필드</p></td><td><code>문자열</code></td></tr><tr><td><a href="#dedup"><code>중복 제거</code></a></td><td>관련 이벤트를 그룹화하는 문자열이며, 최대 1000자까지</td><td><p>Python/YAML에서: <code>title()</code> > <code>DisplayName</code> > <code>RuleID</code> 또는 <code>PolicyID</code></p><hr><p>콘솔에서는: <code>title()</code> > <strong>Name</strong> 필드 > <strong>ID</strong> 필드</p></td><td><code>문자열</code></td></tr><tr><td><a href="#unique"><code>고유</code></a></td><td>고유 임계값 디택션을 위해 추적할 값</td><td>N/A - 표준 이벤트 수 임계값 적용 사용</td><td><code>문자열</code></td></tr><tr><td><a href="#alert_context"><code>알러트_컨텍스트</code></a></td><td>알러트 대상에 전달할 추가 컨텍스트</td><td></td><td><code>Dict[String: Any]</code></td></tr><tr><td><a href="#runbook"><code>런북</code></a></td><td>알러트가 생성된 후 따라야 할 지침 목록입니다. 설명적인 런북을 제공하는 것이 권장됩니다, as <a href="/pages/6e9f85a6a2f1c7f2fb9c3093e77d535eff45c9f4#panther-ai-alert-triage">Panther AI 알러트 분류</a> 이를 고려할 것이기 때문입니다.</td><td><p>YAML에서는: <code>런북</code> 키</p><hr><p>콘솔에서는: <strong>런북</strong> 필드</p></td><td><code>문자열</code></td></tr><tr><td><a href="#reference-and-description"><code>description</code></a></td><td>룰이 존재하는 이유에 대한 설명</td><td><p>YAML에서는: <code>설명</code> 키</p><hr><p>콘솔에서는: <strong>설명</strong> 필드</p></td><td><code>문자열</code></td></tr><tr><td><a href="#reference-and-description"><code>참조</code></a></td><td>룰에 대한 내부 문서 또는 온라인 리소스로 연결되는 참조 URL</td><td><p>YAML에서는: <code>Reference</code> 키</p><hr><p>콘솔에서는: <strong>Reference</strong> 필드</p></td><td><code>문자열</code></td></tr><tr><td><a href="#destinations"><code>대상</code></a></td><td>알러트를 보낼 대상의 ID</td><td><p>YAML에서는: <code>OutputIds</code> 키</p><hr><p>콘솔에서는: <strong>대상 재정의</strong> 필드</p></td><td><code>List[대상 이름/ID]</code></td></tr></tbody></table>

#### `심각도`

일부 시나리오에서는 알러트의 심각도 수준을 상향 또는 하향 조정해야 할 수 있습니다. 알러트의 심각도 수준은 다음에 매핑될 수 있습니다 `정보`, `낮음`, `보통`, `높음`, `치명적`, 또는 `기본값`. 반환 `기본값` 하여 정적으로 정의된 룰 심각도로 되돌아가게 합니다.

심각도 문자열은 대소문자를 구분하지 않으므로, 예를 들어 다음과 같이 반환할 수 있습니다 `치명적` 또는 `기본`, 스타일 선호도에 따라 다릅니다.

아래 예시에서 API 토큰이 생성된 경우, `높음` 심각도의 알러트가 생성되고, 그렇지 않으면 `정보` 수준의 알러트가 생성됩니다:

```python
def severity(event):
    if event.get('eventType') == 'system.api_token.create':
        return "HIGH"
    return "INFO"
```

참조: [템플릿 룰](https://github.com/panther-labs/panther-analysis/blob/master/templates/example_rule.py#L33)

다음을 사용하는 예시 `기본값`:

```python
def severity(event):
    if event.get('eventType') == 'system.api_token.create':
        return "HIGH"
    return "DEFAULT"
```

#### `제목`

the `title()` 함수는 선택 사항이지만, 알러트에 추가 컨텍스트를 제공하기 위해 포함하는 것이 권장됩니다.

아래 예시에서는 로그 유형, 사용자 이름, 그리고 정적 문자열이 알러트 대상에 전송됩니다. 이 함수는 이벤트가 AWS.CloudTrail 로그 유형과 관련이 있는지 확인하고, 그렇다면 AWS 계정 이름을 반환합니다.

알러트 제목이 어떻게 설정되는지 자세히 알아보려면 다음을 참조하세요 [규칙 및 예약 규칙](/ko/detections/rules.md#title-of-associated-alerts).

예시:

```python
def title(event):
    # 제목에 통합 데이터 모델 필드 사용
    log_type = event.get("p_log_type")
    title_str = (
        f"{log_type}: User [{event.udm('actor_user')}] has exceeded the failed logins threshold"
    )
    if log_type == "AWS.CloudTrail":
        title_str += f" in [{lookup_aws_account_name(event.get('recipientAccountId'))}]"
    return title_str
```

참조: [템플릿 룰](https://github.com/panther-labs/panther-analysis/blob/master/templates/example_rule.py#L15)

#### `중복 제거`

중복 제거는 중복 알러트를 받는 것을 방지하기 위해 관련 이벤트를 하나의 알러트로 그룹화하는 프로세스입니다. 중복 제거 기간 내에 동일한 디택션을 트리거하고 동일한 중복 제거 문자열도 공유하는 이벤트는 하나의 알러트로 함께 그룹화됩니다. The `중복 제거` 함수는 중복 제거 문자열을 정의하는 한 가지 방법입니다. 길이는 1000자로 제한됩니다.

중복 제거에 대해 자세히 알아보려면 다음을 참조하세요 [규칙 및 예약 규칙](/ko/detections/rules.md#deduplication).

예시:

```python
def dedup(event):
	user_identity = event.get("userIdentity", {})

	if user_identity.get("type") == "AssumedRole":
		return helper_strip_role_session_id(user_identity.get("arn", ""))

	return user_identity.get("arn")
```

참조: [AWS S3 버킷 삭제 룰](https://github.com/panther-labs/panther-analysis/blob/4b6b79846fb4cb1596908fd31ce983c75a39baaa/aws_cloudtrail_rules/aws_s3_bucket_deleted.py)

#### `고유`

the `unique()` 함수는 고유 값 임계값 디택션을 가능하게 하며, 총 이벤트 수가 아니라 고유 값의 개수를 기준으로 룰이 알러트하도록 합니다. 이는 분산 공격, 데이터 유출, 관리자 남용 시나리오를 탐지하는 데 유용합니다.

여러 사용자에 걸친 로그인 브루트포스를 디텍션하는 예시:

```python
def 룰(event):
    return (
        event.get("eventType") == "user.session.start" and
        event.get("outcome", {}).get("result") == "FAILURE"
    )

def unique(event):
    # 대상이 되는 고유 사용자 이름 추적
    return event.get("actor", {}).get("alternateId", "unknown_user")
```

임계값이 5이면, 이 룰은 중복 제거 기간 내에 실패한 로그인 시도가 5개 이상의 고유 사용자 이름을 대상으로 할 때 알러트합니다.

the `unique()` 함수는 항상 문자열을 반환해야 합니다. 여러 필드의 고유성을 위해서는 필드를 연결하세요:

```python
def unique(event):
    user = event.get("username", "")
    ip = event.get("sourceIP", "")
    return f"{user}@{ip}"
```

고유 값 임계값 디택션에 대해 추가 예제를 포함하여 자세히 알아보려면 다음을 참조하세요. [고유 값 임계값 디택션](#unique-value-threshold-detection).

#### **`대상`**

the `destinations()` function은 룰에서 발생한 알러트를 어떤 알러트 대상(들)로 보낼지 지정하는 방법입니다. 이 설정은 다른 모든 알러트 대상 구성보다 우선합니다(즉, 이것은 [시나리오 1](/ko/alerts/destinations.md#scenario-1-dynamically-defined-destination-s-on-the-detection) 의 예를 확인하세요 [알러트 라우팅 시나리오](/ko/alerts/destinations.md#alert-routing-scenarios)).

the `destinations()` function은 하나 이상의 알러트 대상 이름 또는 UUID 목록을 반환해야 합니다. 만약 function이 반환한 목록이 비어 있으면( `destinations()` function이 비어 있으면 (`[]`), 알러트는 어떤 대상에도 라우팅되지 않습니다.

예를 들어, 아래 룰은 여러 로그 유형과 연결되어 있습니다. 로그 유형이 `AWS.CloudTrail`, `destinations()` 알러트를 다음으로 라우팅합니다: `slack-security-alerts` 대상입니다. 로그 유형이 `AWS.CloudTrail`이 아니면, 외부 대상에는 알러트가 전송되지 않습니다—다음으로 표시됩니다: `return []`.

```python
def destinations(event):
    if event.get("p_log_type") == "AWS.CloudTrail":
        return ["slack-security-alerts"] # 대상의 이름 또는 UUID
    # 외부 대상에 알러트를 보내지 않음
    return []
```

다음의 다른 예시를 참조하세요. [panther-analysis example\_룰](https://github.com/panther-labs/panther-analysis/blob/main/templates/example_rule.py#L66).

#### `알러트_컨텍스트`

이 함수는 디택션이 사용자 이름, IP 주소, 성공/실패와 같은 모든 이벤트 세부 정보를 추가 컨텍스트로 알러트 대상에 전달할 수 있게 합니다.

알러트 컨텍스트 사전에 포함되는 값은 JSON 규격을 준수해야 합니다. 규격을 준수하지 않는 값의 예로는 Python의 `nan`, `inf`및 `-inf`.

예시:

아래 코드는 알러트 컨텍스트에 모든 이벤트 데이터를 반환합니다.

```python
def 룰(event):
    return (
        event.get("actionName") == "UPDATE_SAML_SETTINGS"
        그리고 event.get("actionResult") == "SUCCEEDED"
    )

def 알러트_context(event):
    return {
        "user": event.udm("actor_user"),
        "ip": event.udm("source_ip")
    }
```

#### `런북`

the `런북` 함수 출력은 이 디택션으로 생성된 알러트를 분류하기 위한 실행 가능한 조사 단계를 제공해야 합니다.

다음 경우 [Panther AI가 알러트를 분류합니다](/ko/alerts.md#panther-ai-alert-triage)를 읽고 자동으로 런북을 실행합니다. 효과적인 런북을 작성하는 방법에 대해 더 알아보세요. [알러트 런북](/ko/alerts/alert-runbooks.md).

예시:

```python
def runbook(event):
    user_arn = event.deep_get("userIdentity", "arn", default="this user")
    source_ip = event.deep_get("sourceIPAddress", default="this IP address")
    
    return f"""
    1. 알러트 이전 24시간 동안 {user_arn}의 모든 API 호출을 찾습니다
    2. 소스 IP {source_ip}가 알려진 클라우드 제공업체 IP 범위 또는 VPN 엔드포인트와 연결되어 있는지 확인합니다
    3. 지난 7일 동안 {user_arn} 또는 {source_ip}에서 발생한 다른 알러트를 찾습니다
    """
```

#### `참조` Run Panther AI `description`

the `참조` Run Panther AI `description` 함수는 알러트가 트리거된 이유와 관련 문제를 해결하는 방법에 대한 추가 맥락을 제공할 수 있습니다.

아래 예시는 다음 안에 링크를 동적으로 제공합니다 `참조` 알러트의 필드:

```python
def reference(event):
	log_type = event.get("p_log_type")
	if log_type == "OnePassword.SignInAttempt":
		return: f"<https://link/to/resource>"
	elif log_type == "Okta.SystemLog":
		return: f"<https://link/to/resource/2>"
	else: 
		return: f"<https://default/link>"
```

## 이벤트 객체 함수

Python 디택션에서, `룰()` 함수와 모든 [동적 알러트 함수](#alert-functions-in-python-detections) 단일 인수인 다음을 받습니다: `이벤트` 객체. 이 이벤트 객체에는 이벤트 값의 간단한 추출을 가능하게 하는 내장 함수가 있습니다.

### `get()`

{% code title="함수 시그니처" %}

```python
def get(self, key, default=None) -> Any:
```

{% endcode %}

다음을 사용하여 `get()` 최상위 이벤트 필드에 접근하기 위해 사용합니다. 키를 찾지 못하면 반환될 기본값을 제공할 수 있습니다.

또한 다음을 사용하여 최상위 필드에 접근할 수도 있습니다. [`deep_get()`](#deep_get) Run Panther AI [`deep_walk()`](#deep_walk). 다음에서 [최상위 필드에 안전하게 접근하는 방법에 대해 자세히 알아보세요](#accessing-top-level-fields-safely).

예시:

{% code title="예제 이벤트" %}

```json
{
  "key": "value"
}
```

{% endcode %}

{% code title="get() 사용" %}

```python
def 룰(event):
    return event.get("key") == "value"

# 위 코드는 true를 반환합니다
```

{% endcode %}

### `deep_get()`

{% code title="함수 시그니처" %}

```python
def deep_get(self, *keys: str, default: Any = None) -> Any:
```

{% endcode %}

다음을 사용하여 `deep_get()` Python 딕셔너리 안에 중첩된 키를 반환하는 데 사용합니다.

가져와야 하는 값이 리스트 안에 있다면, 대신 다음을 사용하세요 [`deep_walk()`](#deep_walk) .

{% hint style="info" %}
이 함수는 [전역 헬퍼로도 제공되지만](/ko/detections/rules/python/globals.md#deep_get), 편의상 이 이벤트 객체 함수를 사용하는 것이 권장됩니다.
{% endhint %}

예시:

다음 구조를 가진 이벤트가 주어졌을 때

{% code title="예제 이벤트" %}

```json
{
  "object": {
    "nested": {
       "key": "here"
      }
   }
 }
```

{% endcode %}

{% code title="deep\_get() 사용" %}

```python
def 룰(event):
    return event.deep_get("object", "nested", "key") == "here"
    
# 위 코드는 true를 반환합니다
```

{% endcode %}

### `deep_walk()`

{% code title="함수 시그니처" %}

```python
def deep_walk(
        self, *keys: str, default: Optional[str] = None, return_val: str = "all"
    ) -> Union[Optional[Any], Optional[List[Any]]]:
```

{% endcode %}

다음을 사용하여 `deep_walk()` Python 딕셔너리 안에서 깊게 중첩된 키와 연관된 값을 반환하는 데 사용하며, 딕셔너리나 리스트를 여러 개 포함할 수 있습니다. 여러 이벤트 필드와 일치하면 일치 항목의 배열이 반환되고, 하나만 일치하면 해당 값이 반환됩니다.

{% hint style="info" %}
이 함수는 [전역 헬퍼로도 제공되지만](/ko/detections/rules/python/globals.md#deep_walk), 편의상 이 이벤트 객체 함수를 사용하는 것이 권장됩니다.
{% endhint %}

예시:

{% code title="예제 이벤트" %}

```json
{
  "object": {
    "nested": {
       "list": [
          {
             "key": "first"
          },
          {
             "key": "second"
          }
         ]
      }
   }
 }
```

{% endcode %}

{% code title="deep\_walk() 사용" %}

```python
def 룰(event):
    return "first" in event.deep_walk("object", "nested", "list", "key", default=[])

# 위 코드는 true를 반환합니다
```

{% endcode %}

### `lookup()`

{% code title="함수 시그니처" %}

```python
def lookup(self, lookup_table_name: str, lookup_key: str) -> Any:
```

{% endcode %}

the `lookup()` 함수를 사용하면 다음에서 데이터를 동적으로 접근할 수 있습니다. [사용자 지정 룩업 테이블](https://docs.panther.com/enrichment) Run Panther AI [Panther가 관리하는 보강 제공자](/ko/enrichment.md) 를 탐지 규칙에서 사용할 수 있습니다. 다음 `lookup()` 함수는 들어오는 로그에 Lookup Table의 기본 키 열 값과 정확히 일치하는 값이 없을 때 유용할 수 있습니다. Python을 사용해 이벤트 값을 수정한 뒤 `lookup()` 에 전달하여 보강 데이터를 가져올 수 있습니다.

`lookup()` 두 개의 인수를 받습니다:

* Lookup Table의 이름
  * 다음에 전달되는 Lookup Table 이름 `lookup()` 은 에 표시된 이름과 같아야 합니다. **Enrichment Providers** 또는 **조회 테이블** Panther Console의 페이지입니다. 이 이름은 검색 쿼리에서 표시되는 방식과 문법적으로 다를 수 있습니다. 예를 들어, `My-Custom-LUT` 대신 `my_custom_lut`.
* 조회 테이블 기본 키

제공된 키에 대해 조회 테이블에서 일치 항목이 발견되면, 전체 조회 테이블 행이 Python 딕셔너리로 반환됩니다. 일치 항목이 없으면, `None` 이 반환됩니다.

{% hint style="info" %}
이 `lookup()` 함수는, Selector로 지정된 이벤트 필드의 값이 조회 테이블의 기본 키 열 값과 정확히 일치할 때 발생하는 "자동" 이벤트 보강과는 다릅니다. 이 경우 조회 테이블 데이터는 이벤트의 `p_enrichment` 필드에 추가됩니다. 자세한 내용은 [Custom Lookup Tables의 로그와 조회 테이블 간 데이터는 어떻게 매칭되나요?를 참조하세요.](/ko/enrichment/custom.md#how-is-data-matched-between-logs-and-lookup-tables).

이러한 방식으로 "자동" 보강을 사용하는 경우, 중첩된 보강 데이터에는 다음을 사용해 접근하세요. [`deep_walk()`](#deep_walk) .
{% endhint %}

다음을 사용하는 예시 `lookup()`:

```python
# user_roles라는 이름의 조회 테이블이 있고 다음 항목들이 있다고 가정합니다:
# 1행: {"id": "your@email.com", "role": "admin"}
# 2행: {"id": "vistor@email.com", "role": "guest"}

# 이 룰에서는 사용자가 admin이 아닌 역할을 가지면 True를 반환하려고 합니다
# 조회 테이블에서 role을 가져오고 싶지만, 이벤트에는 
# 조회 테이블의 기본 키(이메일 주소)가 포함되어 있지 않습니다
def 룰(event):
    lookup_table_name = "user_roles"
    # 이벤트에서는 사용자 이름에 접근할 *수는* 있으며, 이를 통해
    # 이메일 주소를 생성할 수 있습니다
    user_name = event.get("username", "").lower()
    lookup_key = f"{user_name}@email.com" # 조회 키 또는 "Selector"를 동적으로 구성
    
    lookup_data = event.lookup(lookup_table_name, lookup_key)
    # 일치 항목이 있으면 `lookup_data`에는 전체 데이터 행이 포함됩니다
    # 그렇지 않으면 None을 반환합니다
    
    if (lookup_data and lookup_data.get("role") != "admin") or lookup_data is None:
        True를 반환
        
    return False
```

#### 다음을 사용하는 디택션의 단위 테스트 `lookup()`

다음 경우 [단위 테스트](/ko/detections/testing.md) 가 실행될 때, `lookup()` 는 라이브 데이터를 가져오지 않습니다. 조회 기능을 에뮬레이션하려면, 각 단위 테스트의 이벤트 페이로드에 `_mocked_lookup_data_` 필드를 추가하여 조회 테이블 데이터를 모의 처리하세요. 다음은 사용할 수 없습니다. [테스트 데이터 보강 버튼 또는 CLI 명령](/ko/detections/testing.md#enrich-test-data) 다음과 함께 `lookup()`.

`_mocked_lookup_data_` 은 다음 예시처럼 구성되어야 합니다:

{% code title="event.lookup() 모의 처리" %}

```json5
{
  "_mocked_lookup_data_": {
     "user_roles": { # 이 키는 조회 테이블의 이름입니다
         # 이 객체의 키는 조회 테이블 키여야 합니다
         # 이 객체의 값은 조회 테이블 데이터 객체여야 합니다
         "your@email.com": {"id": "your@email.com", "role": "admin"},
         "vistor@email.com": {"id": "vistor@email.com", "role": "guest"}
      }
   }
}
```

{% endcode %}

만약 `_mocked_lookup_data_` 필드를 단위 테스트에 지정하지 않으면, 다음 호출 시도는 `lookup()` 를 반환합니다 `None/null`.

### `udm()`

{% code title="함수 시그니처" %}

```python
def udm(self, *key: str, default: Any = None) -> Any:
```

{% endcode %}

the `udm()` 함수는 주로 [데이터 모델](/ko/detections/rules/python/data-models.md)에 접근할 수 있도록 하기 위한 것이지만, 이벤트 필드에 접근하는 데에도 사용할 수 있습니다.

다음은 `udm()` 함수가 작동하는 방식입니다:

1. 이 함수는 먼저 [데이터 모델](/ko/detections/rules/python/data-models.md) 에 전달된 값에 대해 정의된 키 매핑이 있는지 확인합니다 `udm()`그렇다면 데이터 모델의 값이 반환됩니다.
   * 만약 [데이터 모델](/ko/detections/rules/python/data-models.md) 에 전달된 값에 대해 키가 정의되어 있으면, `udm()`함수는 해당 값을 반환하고 아래의 2단계로 넘어가지 않습니다. 이는 평가 중인 이벤트에 데이터 모델 매핑에 정의된 키 경로가 포함되어 있지 않더라도 마찬가지이며, 이 경우에는 `null` 이 반환됩니다.
2. 만약 [데이터 모델](/ko/detections/rules/python/data-models.md) 에 전달된 값에 대해 정의된 항목이 없으면, `udm()`함수는 그다음 해당 이름의 이벤트 필드가 있는지 확인합니다. 있으면 그 값이 반환됩니다.
   * 이 경우, `udm()` 는 중첩된 필드를 포함한 모든 이벤트 필드를 확인합니다. 그 동작은 다음과 유사합니다 [`deep_get()`](#deep_get).

{% hint style="info" %}
위에서 설명한 동작은 다음을 사용하는 것이 가능하다는 의미입니다. `udm()` 에 동일한 키로 정의된 [데이터 모델](/ko/detections/rules/python/data-models.md) 매핑도 없는 경우에만 이벤트 필드 값에 접근할 수 있습니다.
{% endhint %}

{% code title="udm 사용 예시" %}

```python
# 데이터 모델에서 작업할 때의 예시 사용법 
def 룰(event):
  return event.udm('field_on_data_model')
  
# 기본값과 함께 데이터 모델에서 작업할 때의 예시 사용법
def 룰(event):
  # default 매개변수는
  # 데이터 모델에서 경로 기반 매핑을 사용할 때에만 적용됩니다. 데이터 모델이 함수에 매핑되는 경우, 해당
  # 함수가 반환하는 값이 그대로 사용됩니다
  return event.udm('field_on_data_model', default='')
  
```

{% endcode %}

#### 다음을 사용하는 예시 `udm()` 다음에 접근하기 위해 [데이터 모델](/ko/detections/rules/python/data-models.md) 값:

{% code title="데이터 모델 예시" %}

```yaml
매핑:
  - 이름: source_ip
    경로: nested.srcIp
```

{% endcode %}

{% code title="예제 이벤트" %}

```json
{
  "nested": {
    "srcIp": "127.0.0.1"
  }
}
```

{% endcode %}

{% code title="udm() 사용" %}

```python
def 룰(event):
    return event.udm("source_ip") == "127.0.0.1"

# 위 코드는 true를 반환합니다
```

{% endcode %}

## 고유 값 임계값 디택션

Panther는 고유값 임계치 디택션을 지원하며, 이를 통해 룰은 단순한 전체 이벤트 수가 아니라 관찰된 고유값 수를 기준으로 알러트할 수 있습니다(예: "고유한 IP 주소 10개 이상이 보이면 알러트"). 이는 다음과 같은 시나리오를 디택션하는 데 유용합니다:

* 서로 다른 IP 주소에서 발생하는 여러 로그인 시도
* 여러 사용자 이름을 대상으로 하는 무차별 대입 공격
* 다양한 외부 도메인으로의 데이터 유출
* 여러 리소스에 영향을 미치는 관리 작업

### the `unique()` 함수

고유값 임계치 디택션을 활성화하려면, Python 룰에 `unique()` 고유한 것으로 계산해야 할 대상을 나타내는 문자열 값을 반환하는 함수를 정의하세요.

{% code title="함수 시그니처" %}

```python
def unique(event) -> str:
```

{% endcode %}

the `unique()` 함수는 추적할 고유값을 식별하는 문자열을 반환해야 합니다. 일반적인 예로는 IP 주소, 사용자 이름, 도메인 이름 또는 리소스 ID가 있습니다.

#### 예시: 다중 IP 로그인 디택션

```python
def 룰(event):
    # 이것이 성공한 로그인 이벤트인지 확인
    return (
        event.get("eventName") == "ConsoleLogin" and
        event.deep_get("responseElements", "ConsoleLogin") == "Success"
    )

def unique(event):
    # 고유한 소스 IP 주소 추적
    return event.get("sourceIPAddress")

# threshold=5이면, 고유 IP가 5개 이상일 때 알러트합니다
# 중복 제거 기간 내에 성공한 로그인이 있을 경우
```

#### 예시: 다중 대상 무차별 대입 디택션

```python
def 룰(event):
    # 로그인 실패 시도 확인
    return (
        event.get("eventType") == "user.session.start" and
        event.get("outcome", {}).get("result") == "FAILURE"
    )

def unique(event):
    # 공격받는 고유 대상 사용자 이름 추적
    return event.get("actor", {}).get("alternateId")

# threshold=10이면, 서로 다른 사용자 10명 이상이 있을 때 알러트합니다
# 중복 제거 기간 내에 로그인 실패 시도를 경험하는 경우
```

#### 예시: 데이터 유출 디택션

```python
def 룰(event):
    # 클라우드 스토리지에서의 파일 다운로드 찾기
    return (
        event.get("eventName") == "GetObject" and
        event.get("responseElements", {}).get("x-amz-request-charged") != "requester"
    )

def unique(event):
    # 접근되는 고유 파일 추적
    bucket = event.get("requestParameters", {}).get("bucketName", "")
    key = event.get("requestParameters", {}).get("key", "")
    return f"{bucket}/{key}"

# threshold=50이면, 고유 파일이 50개 이상일 때 알러트합니다
# 중복 제거 기간 내에 다운로드되는 경우
```

### 고유값 임계치 처리 방식

다음을 정의하면 `unique()` 함수:

1. **값 추출**: 일치하는 각 이벤트에 대해 Panther는 `unique()` 함수를 호출하여 추적할 고유값을 추출합니다
2. **확률적 카운팅**: Panther는 메모리 효율적인 확률적 알고리즘을 사용하여 관찰된 고유값 수를 추정합니다
3. **임계치 확인**: 추정된 고유 개수가 구성된 임계치에 도달하면 알러트가 생성됩니다
4. **중복 제거**: 고유 개수는 룰의 중복 제거 기간에 따라 초기화됩니다

### 구성 요구 사항

고유값 임계치 처리를 사용하려면:

* 다음을 정의하세요 `unique()` 문자열을 반환하는 함수
* 룰의 **Threshold** 를 알러트를 트리거하는 데 필요한 최소 고유값 수로 설정하세요(기본값: 1)
* 적절한 **중복 제거 기간** 를 사용 사례에 맞게 구성하세요(기본값: 1시간)

### 성능 고려 사항

* **정확도**: 고유 카운팅 알고리즘은 최대 1,000개의 고유값 카디널리티에 대해 약 90%의 정확도를 제공합니다
* **메모리 효율성**: 고유값 수와 관계없이 알러트당 약 16KB의 스토리지를 사용합니다
* **권장 한도**: 임계치가 1,000개의 고유값 미만일 때 최상의 성능을 보입니다
* **연결**: 다중 필드 고유성의 경우, `unique()` 함수: `return f"{ip}:{username}"`

### 하위 호환성

가 없는 룰은 `unique()` 함수가 없는 경우 계속해서 표준 이벤트 수 임계치 처리를 사용합니다. 기존 룰에 `unique()` 함수를 추가하거나 제거하면 알러트 동작이 변경됩니다.

## Python 모범 사례

Python Enhancement Proposals [는 리소스를 제공합니다](https://peps.python.org/pep-0008/) Python 코드를 깔끔하고 효과적으로 작성하고 스타일링하는 방법에 대해 설명합니다. 예를 들어, [autopep8](https://pypi.org/project/autopep8/) 를 사용하여 작성한 디택션이 모두 일관된 스타일을 따르도록 자동으로 보장할 수 있습니다.

### 사용 가능한 Python 라이브러리

다음 Python 라이브러리는 Panther에서 `boto3`외에도 사용할 수 있으며, 이는 [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html):

<table data-header-hidden><thead><tr><th width="204">패키지</th><th width="174">버전</th><th width="186">설명</th><th>라이선스</th></tr></thead><tbody><tr><td>패키지</td><td>버전</td><td>설명</td><td>라이선스</td></tr><tr><td><code>jsonpath-ng</code></td><td><code>1.5.2</code></td><td>JSONPath 구현</td><td>Apache v2</td></tr><tr><td><code>policyuniverse</code></td><td><code>1.3.3.20210223</code></td><td>AWS ARN 및 정책 파싱</td><td>Apache v2</td></tr><tr><td><code>requests</code></td><td><code>2.23.0</code></td><td>간편한 HTTP 요청</td><td>Apache v2</td></tr></tbody></table>

## Python 디택션 작성 모범 사례

### 디택션 테스트 작성

새 디택션을 활성화하기 전에, [테스트를 작성하는 것이 권장됩니다 ](/ko/detections/testing.md)알러트가 생성되어야 하는 경우와 생성되지 않아야 하는 경우를 정의하는 테스트입니다. 가장 높은 신뢰성을 보장하기 위해 최소 하나의 긍정 사례와 하나의 부정 사례를 두는 것이 모범 사례입니다.

### 이벤트 필드의 대소문자

이벤트 필드 조회는 대소문자를 구분하지 않습니다. `event.get("Event_Type")` 또는 `event.get("event_type")` 는 같은 결과를 반환합니다.

### 최상위 필드와 중첩 필드 이해하기

최상위 필드는 중첩 데이터 구조에서 부모 필드를 나타냅니다. 예를 들어, 레코드에는 `user` 라는 필드가 있을 수 있으며, 그 아래에 `ip_address`와 같은 다른 필드가 있습니다. 이 경우, `user` 는 최상위 필드이고, `ip_address` 는 그 아래의 중첩 필드입니다.

중첩은 여러 계층 깊이에서 발생할 수 있으므로, 스키마 구조를 이해하고 디택션을 위해 특정 필드에 접근하는 방법을 아는 것이 중요합니다.

### **최상위 필드에 안전하게 접근하기**

기본 룰은 이벤트에서 필드의 값과 일치하며, 오류를 피하기 위한 모범 사례는 Python의 내장 [`get()`](#get) 함수를 활용하는 것입니다.

아래 예시는 `get()` 함수를 활용하는 것입니다. `get()` 가 필드를 찾고, 해당 필드가 존재하지 않으면 오류 대신 `None` 를 반환하므로 디택션이 반환되는 결과를 초래한다는 점에서 모범 사례입니다. `False`.

```python
def 룰(event):
    return event.get('field') == 'value'
```

아래 예시에서는 필드가 존재하면 해당 필드의 값이 반환됩니다. 그렇지 않으면, `False` 가 반환됩니다:

```python
def 룰(event):
    if event.get('field')
        return event.get('field')
    return False
```

{% hint style="warning" %}
**잘못된 관행 예시**\
아래의 룰 정의는 코드가 필드 이름을 명시적으로 적고 있기 때문에 잘못된 관행입니다. 필드가 존재하지 않으면 Python은 `KeyError`:

```python
def 룰(event):
    return event['field'] == 'value'
```

{% endhint %}

### Global Helper 함수 사용하기

많은 디택션이 작성되면, 패턴과 반복되는 코드가 나타나기 시작합니다. 이는 다음의 훌륭한 사용 사례입니다. [Global Helper 함수](/ko/detections/rules/python/globals.md)이며, 이 로직이 모든 디택션 전반에서 존재할 수 있도록 중앙화된 위치를 제공합니다.

### 중첩된 필드를 안전하게 접근하기

이벤트 안에 깊게 중첩된 필드에 접근하고 싶다면, [`deep_get()`](#deep_get) Run Panther AI [`deep_walk()`](#deep_walk) 이벤트 객체에서 사용할 수 있는 함수들을 사용하세요. 이 함수들은 또한 [Global Helper 함수](/ko/detections/rules/python/globals.md)로도 표현되지만, 편의상 대신 이벤트 객체 버전을 사용하는 것이 권장됩니다.

예시:

AWS CloudTrail 로그는 `type` 콘솔에 접근하는 사용자의 `userIdentity`아래에 중첩합니다. 다음은 JSON CloudTrail 루트 활동 로그의 일부입니다:

```json
{ 	
       "eventVersion": "1.05",
       "userIdentity": { 	
               "type": "Root", 	
               "principalId": "1111", 	
               "arn": "arn:aws:iam::123456789012:root", 	
               "accountId": "123456789012", 		
               "userName": "root" 
               }, 	
        ... 
 }
```

의 값을 확인하는 방법을 보세요 `type` 두 가지 형태의 `deep_get()`:

{% tabs %}
{% tab title="deep\_get() 이벤트 객체 함수를 사용하여 안전하게" %}
이벤트 값을 확인하기 [이벤트 객체를 사용하여 `deep_get()` 함수](#deep_get):

```python
def 룰(event):
    return event.deep_get("userIdentity", "type") == "Root"
```

{% endtab %}

{% tab title="deep\_get() Global Helper 함수" %}
이벤트 값을 확인하기 [`deep_get()` Global Helper 함수](/ko/detections/rules/python/globals.md#deep_get):

```python
from panther_base_helpers import deep_get

def 룰(event):
    return deep_get(event, "userIdentity", "type") == "Root"
```

{% endtab %}
{% endtabs %}

### **특정 값에 대한 필드 확인하기**

특정 이벤트가 발생했는지 알고 싶을 수 있습니다. 해당 이벤트가 발생했다면, 디택션은 알러트를 트리거해야 합니다. Panther는 모든 것을 정규화된 JSON으로 저장하므로, 지정한 기준에 대해 필드의 값을 확인할 수 있습니다.

예를 들어, Box 계정에 Box 기술 지원 액세스를 부여하는 동작을 탐지하려면, 아래 Python은 다음 값과 일치하는 이벤트를 매칭하는 데 사용됩니다. `event_type` 와 같고 `ACCESS_GRANTED`:

```python
def 룰(event):
    return event.get("event_type") == "ACCESS_GRANTED"
```

필드가 `event_type` 이고 값이 `ACCESS_GRANTED` 와 같다면, 룰 함수는 `true` 그리고 알러트가 생성됩니다.

### 정수 값에 대해 필드 확인하기

필드의 값을 정수와 비교해야 할 수 있습니다. 이렇게 하면 이벤트에 대해 Python의 내장 비교 연산을 사용할 수 있습니다.

예를 들어, HTTP 응답 상태 코드에 기반한 알러트를 만들 수 있습니다:

```python
# 'status_code'가 404와 같으면 True를 반환
def 룰(event):
    if event.get("status_code"):
        return event.get("status_code") == 404
    else:
        return False

# 'status_code'가 400보다 크면 True를 반환
def 룰(event):
    if event.get("status_code"):
        return event.get("status_code") > 404
    else:
        return False
```

참조:

* [box\_access\_granted.py](https://github.com/panther-labs/panther-analysis/blob/cd220c87982011d4ad156c7daecd2857c358d154/rules/box_rules/box_access_granted.py)
* [Python 연산자](https://www.w3schools.com/python/python_operators.asp)

### **Universal Data Model 사용하기**

[데이터 모델](/ko/detections/rules/python/data-models.md) 모든 로그 유형에 걸쳐 통합된 필드 집합을 구성하는 방법을 제공합니다. 기본적으로 Panther에는 여러 로그 유형에 대한 기본 제공 데이터 모델이 포함되어 있습니다. 사용자 정의 데이터 모델은 Panther Console 또는 다음을 통해 추가할 수 있습니다. [Panther Analysis Tool](https://docs.panther.com/writing-detections/panther-analysis-tool#data-models).

[`event.udm()`](#udm) 은(는) Panther 환경에 기존 데이터 모델이 있는 로그 유형에만 사용할 수 있습니다.

예시:

```python
import panther_event_type_helpers as event_type

def 룰(event):
    # 통합 데이터 모델 필드 ‘event_type’에 따라 이벤트 필터링
    return event.udm("event_type") == event_type.FAILED_LOGIN
```

참조:

* [데이터 모델 가이드](https://docs.panther.com/writing-detections/data-models)
* [데이터 모델](https://github.com/panther-labs/panther-analysis/tree/master/data_models)
* [IP를 이용한 무차별 대입](https://github.com/panther-labs/panther-analysis/blob/cd220c87982011d4ad156c7daecd2857c358d154/indexes/standard.md)

### 여러 조건 사용하기

the `Run Panther AI` keyword는 논리 연산자이며 조건문을 결합하는 데 사용됩니다. 다음을 사용하여 이벤트의 여러 필드를 일치시켜야 하는 경우가 많습니다. `Run Panther AI` keyword를. 사용할 때 `Run Panther AI`, 모든 문은 참이어야 합니다:\
`"string_a" == "this"`**`Run Panther AI`**`"string_b" == "that"`

예시:

AWS 콘솔에 대한 루트 사용자 성공 액세스를 추적하려면 여러 필드를 살펴봐야 합니다:

```python
from panther_base_helpers import deep_get

def 룰(event):
    return (event.get("eventName") == "ConsoleLogin" and
            deep_get(event, "userIdentity", "type") == "Root" and
	    deep_get(event, "responseElements", "ConsoleLogin") == "Success")
```

the `또는` keyword는 논리 연산자이며 조건문을 결합하는 데 사용됩니다. 사용할 때 `또는`, 두 문 중 어느 하나라도 참일 수 있습니다:\
"` string_a" == "this"`` `` `**`또는`**` `` ``"string_b" == "that" `

예시:

이 예시는 필드에 포트 80이 포함되어 있는지 **또는** 포트 22가 포함되어 있는지 감지합니다:

```python
# 'port_number'가 80 또는 22이면 True를 반환
def 룰(event):
    return event.get("port_number") == 80 or event.get("port_number") == 22
```

### 리스트에서 값 검색하기

이벤트 값을 리스트(예: IP 주소나 사용자 포함)와 비교하는 것은 Python에서 빠릅니다. 흔한 패턴은 이벤트 값이 리스트에도 존재할 때 룰 로직이 일치하지 않도록 설정하는 것입니다. 이는 환경에서 알려진 동작에 대한 오탐을 줄이는 데 도움이 될 수 있습니다.

이벤트 값이 어떤 컬렉션에 포함되어 있는지 확인할 때는 Python set을 사용하는 것이 권장됩니다. set은 Python에서 리스트와 튜플보다 더 성능이 좋고(즉, 메모리 효율적이며), 리스트와 튜플은 set과 달리 포함 여부를 확인하려면 컬렉션의 각 항목을 하나씩 순회해야 합니다.

비교하는 대상 set이 정적이라면, 함수 내부가 아니라 전역 수준에서 정의하는 것이 권장됩니다. `룰()` 함수. 전역 변수는 Lambda 호출당 한 번만 초기화됩니다. 단일 Lambda 호출이 여러 이벤트를 처리할 수 있으므로, 전역 변수는 보통 매번 초기화하는 것보다 더 효율적입니다. `룰()` 이 호출될 때.

예시:

```python
# Set - 성능 면에서 튜플과 리스트보다 권장됨
ALLOW_IP = {'192.0.0.1', '192.0.0.2', '192.0.0.3'}

def 룰(event):
    return event.get("ip_address") not in ALLOW_IP
```

아래 예시에서는 Panther helper를 사용합니다 `pattern_match_list`:

```python
from panther_base_helpers import pattern_match_list

USER_CREATE_PATTERNS = [
    "chage",   # 사용자 비밀번호 만료
    "passwd",  # 사용자의 비밀번호 변경
    "user*",   # 사용자 생성, 수정 및 삭제
]

def 룰(event):
    # 이벤트 필터링
    if event.get("event") != "session.command":
        return False
    # 프로그램이 위의 목록과 일치하는지 확인
    return pattern_match_list(event.get("program", ""), USER_CREATE_PATTERNS)
```

참조: [Teleport 사용자 계정 생성](https://github.com/panther-labs/panther-analysis/blob/cd220c87982011d4ad156c7daecd2857c358d154/rules/gravitational_teleport_rules/teleport_create_user_accounts.py)

### regex로 이벤트 매칭

정규 표현식을 사용하여 이벤트와 매칭하려는 경우 - 하위 도메인, 파일 경로 또는 일반 문자열의 접두사/접미사를 매칭하기 위해 - regex를 사용할 수 있습니다. Python에서는 `re` 라이브러리를 가져와 일치하는 값을 찾음으로써 regex를 사용할 수 있습니다.

아래 예시에서 regex 패턴은 privilegeGranted 필드의 중첩된 값에 대해 Administrator 또는 administrator와 매칭됩니다.

```python
import re
from panther_base_helpers import deep_get

# regex 패턴은 변수에 저장됩니다
# 참고: 이것을 룰 함수에 넣는 것보다 성능이 더 좋습니다. 룰 함수는 각 이벤트마다 평가됩니다
ADMIN_PATTERN = re.compile(r"[aA]dministrator")

def 룰(event):
    # deep_get 함수를 사용하면 "privilegeGranted" 필드 아래의 중첩된 값을 추출할 수 있습니다
    value_to_search = deep_get(event, "debugContext", "debugData", "privilegeGranted")
    # 마지막으로 앞서 생성한 regex 객체를 사용하여 값과 대조합니다
    # 일치하는 항목이 있으면 "True"가 반환됩니다 
    return (bool(ADMIN_PATTERN.search(value_to_search, default="")))
```

아래 예시에서는 Panther helper를 사용합니다 `pattern_match`:

```python
from panther_base_helpers import pattern_match

def 룰(event):
    return pattern_match(event.get("operation", ""), "REST.*.OBJECT")
```

참조:

* [re.compile](https://docs.python.org/3/library/re.html#functions)
* [Pythex: 간단한 RegEx 편집기 및 테스터](https://pythex.org/)
* [AWS S3 안전하지 않은 액세스](https://github.com/panther-labs/panther-analysis/blob/cd220c87982011d4ad156c7daecd2857c358d154/rules/aws_s3_rules/aws_s3_insecure_access.py)

## Python 룰 사양 참조

필수 필드는 다음에 있습니다 **굵게**.

<table data-header-hidden data-full-width="false"><thead><tr><th width="214.375">필드 이름</th><th width="455">설명</th><th width="302.5081967213115">예상 값</th></tr></thead><tbody><tr><td>필드 이름</td><td>설명</td><td>예상 값</td></tr><tr><td><strong><code>AnalysisType</code></strong></td><td>이 분석이 룰, scheduled_룰, policy 또는 global인지 나타냅니다</td><td>룰: <code>룰</code><br>예약된 룰: <code>scheduled_룰</code></td></tr><tr><td><strong><code>활성화됨</code></strong></td><td>이 룰이 활성화되어 있는지 여부</td><td>불리언</td></tr><tr><td><strong><code>FileName</code></strong></td><td>python 룰 본문에 대한 경로(파일 확장자 포함)</td><td>문자열</td></tr><tr><td><strong><code>RuleID</code></strong></td><td>룰의 고유 식별자</td><td>문자열<br>포함할 수 없음 <code>%</code></td></tr><tr><td><strong><code>LogTypes</code></strong></td><td>이 룰을 적용할 로그 목록</td><td>문자열 목록</td></tr><tr><td><strong><code>심각도</code></strong></td><td>이 룰의 심각도</td><td>다음 문자열 중 하나: <code>정보</code>, <code>낮음</code>, <code>보통</code>, <code>높음</code>, 또는 <code>치명적</code></td></tr><tr><td><strong><code>ScheduledQueries</code></strong> (예약된 룰에만 해당하는 필드)</td><td>이 룰을 적용할 Scheduled Query 이름 목록</td><td>문자열 목록</td></tr><tr><td><code>CreateAlert</code></td><td>룰이 다음을 생성해야 하는지 여부 <a href="/pages/28a2f0a91092222209c65334fa10beb60037d689#signals-vs.-rule-matches-vs.-alerts">룰 일치/알러트</a> 일치 시 (기본값 true)</td><td>불리언</td></tr><tr><td><code>설명</code></td><td>룰에 대한 간단한 설명</td><td>문자열</td></tr><tr><td><code>DedupPeriodMinutes</code></td><td>알러트의 유사한 이벤트가 함께 그룹화되는 기간(분)</td><td><code>15</code>,<code>30</code>,<code>60</code>,<code>180</code> (3시간),<code>720</code> (12시간), 또는 <code>1440</code> (24시간)</td></tr><tr><td><code>DisplayName</code></td><td>UI와 알림에 표시할 친숙한 이름. The <code>RuleID</code> 가 설정되지 않으면 표시됩니다.</td><td>문자열</td></tr><tr><td><code>OutputIds</code></td><td>정적 대상 재정의입니다. 이는 이 룰의 알러트가 어떻게 라우팅될지 결정하는 데 사용되며, 심각도에 따른 기본 라우팅보다 우선합니다.</td><td>문자열 목록</td></tr><tr><td><code>Reference</code></td><td>이 룰이 존재하는 이유로, 보통 문서에 대한 링크입니다</td><td>문자열</td></tr><tr><td><code>Reports</code></td><td>이 룰이 해당 프레임워크에서 어떤 값을 다루는지에 대한 프레임워크 또는 보고서 이름과 값의 매핑</td><td>문자열에서 문자열 목록으로의 맵</td></tr><tr><td><code>런북</code></td><td>분석가 또는 Panther AI가 관련 경고를 분류하기 위해 수행할 수 있는 작업입니다.</td><td>문자열</td></tr><tr><td><code>SummaryAttributes</code></td><td>알러트가 요약해야 하는 필드 목록입니다.</td><td>문자열 목록</td></tr><tr><td><code>Threshold</code></td><td>알러트가 전송되기 전에 이 룰을 트리거해야 하는 이벤트 수입니다.</td><td>정수</td></tr><tr><td><code>Tags</code></td><td>이 룰을 분류하는 데 사용되는 태그</td><td>문자열 목록</td></tr><tr><td><code>Tests</code></td><td>이 룰에 대한 단위 테스트입니다.</td><td>맵 목록</td></tr><tr><td><code>CreatedBy</code></td><td>이 디택션의 작성자입니다. Panther 사용자 UUID, 이메일 주소 또는 임의의 텍스트 값으로 설정할 수 있습니다. 자세한 내용은 다음을 참조하세요 <a href="/pages/5f0ed921cfc97d649f3af6d2a4a6b7d06f7759cc#the-createdby-detection-field">the <code>CreatedBy</code> 디택션 필드</a>.</td><td>문자열</td></tr></tbody></table>

## Python 정책 사양 참조

필수 필드는 다음에 있습니다 **굵게**.

정책 사양 필드의 전체 목록:

<table data-header-hidden data-full-width="false"><thead><tr><th width="169.939208984375">필드 이름</th><th width="528.4545454545455">설명</th><th>예상 값</th></tr></thead><tbody><tr><td>필드 이름</td><td>설명</td><td>예상 값</td></tr><tr><td><strong><code>AnalysisType</code></strong></td><td>이 사양이 정책 또는 룰을 정의하는지 여부를 나타냅니다</td><td><code>정책</code></td></tr><tr><td><strong><code>활성화됨</code></strong></td><td>이 정책이 활성화되어 있는지 여부</td><td>불리언</td></tr><tr><td><strong><code>FileName</code></strong></td><td>파이썬 정책 본문의 경로(파일 확장자 포함)</td><td>문자열</td></tr><tr><td><strong><code>PolicyID</code></strong></td><td>정책의 고유 식별자</td><td>문자열<br>포함할 수 없음 <code>%</code></td></tr><tr><td><strong><code>리소스 유형</code></strong></td><td>이 정책이 적용될 리소스 유형</td><td>문자열 목록</td></tr><tr><td><strong><code>심각도</code></strong></td><td>이 정책의 심각도</td><td>다음 문자열 중 하나: <code>정보</code>, <code>낮음</code>, <code>보통</code>, <code>높음</code>, 또는 <code>치명적</code></td></tr><tr><td><code>설명</code></td><td>정책에 대한 간단한 설명</td><td>문자열</td></tr><tr><td><code>DisplayName</code></td><td>UI와 경고에 표시할 이름. The <code>PolicyID</code> 가 설정되지 않으면 표시됩니다.</td><td>문자열</td></tr><tr><td><code>Reference</code></td><td>이 정책이 존재하는 이유로, 보통 문서 링크입니다</td><td>문자열</td></tr><tr><td><code>Reports</code></td><td>이 정책이 해당 프레임워크에 대해 다루는 값과 프레임워크 또는 보고서 이름의 매핑</td><td>문자열에서 문자열 목록으로의 맵</td></tr><tr><td><code>런북</code></td><td>분석가 또는 Panther AI가 관련 경고를 분류하기 위해 수행할 수 있는 작업입니다.</td><td>문자열</td></tr><tr><td><code>억제</code></td><td>무시할 패턴, 예: <code>aws::s3::*</code></td><td>문자열 목록</td></tr><tr><td><code>Tags</code></td><td>이 정책을 분류하는 데 사용되는 태그</td><td>문자열 목록</td></tr><tr><td><code>Tests</code></td><td>이 정책에 대한 단위 테스트.</td><td>맵 목록</td></tr><tr><td><code>CreatedBy</code></td><td>이 디택션의 작성자입니다. Panther 사용자 UUID, 이메일 주소 또는 임의의 텍스트 값으로 설정할 수 있습니다. 자세한 내용은 다음을 참조하세요 <a href="/pages/5f0ed921cfc97d649f3af6d2a4a6b7d06f7759cc#the-createdby-detection-field">the <code>CreatedBy</code> 디택션 필드</a>.</td><td>문자열</td></tr></tbody></table>

## 탐지 문제 해결

Panther 지식 기반을 방문하여 [탐지에 관한 문서를 보십시오](https://help.panther.com/Detections) 자주 묻는 질문에 답하고 일반적인 오류와 문제를 해결하는 데 도움이 되는


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.panther.com/ko/detections/rules/python.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
