# CSV 로그 파서

## 개요

다음을 사용하여 `csv` 로그 파서로 CSV 파일은 각 행을 키-값을 매핑한 단순한 JSON 객체로 변환하여 파싱됩니다. 이를 위해 각 열에는 이름이 지정되어야 합니다.

## 헤더 없는 CSV 로그

헤더 행이 없는 CSV 로그를 파싱하려면 Panther는 각 열에 어떤 이름을 할당해야 하는지 알아야 합니다.

로그가 year, month, day, time, action, ip\_address, message의 7개 열을 가진 CSV라고 가정해 보겠습니다. 이 파일의 몇 가지 예시 행은 다음과 같을 수 있습니다:

```
# 20200901에 대한 액세스 로그
2020,09,01,10:35:23, SEND ,192.168.1.3,"PING"
2020,09,01,10:35:25, RECV ,192.168.1.3,"PONG"
2020,09,01,10:35:25, RESTART ,-,"System restarts"
```

다음의 *LogSchema* 를 사용해 로그 타입을 정의합니다:

{% tabs %}
{% tab title="콘솔 " %}
Panther 콘솔에서는 다음을 따릅니다 [커스텀 스키마를 수동으로 생성하는 방법 안내](https://docs.panther.com/ko/data-onboarding/custom-log-types/..#how-to-create-a-custom-schema-manually), **CSV** 파서.

<figure><img src="https://2400888838-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LgdiSWdyJcXPahGi9Rs-2910905616%2Fuploads%2Fgit-blob-b5f84896b7f48030c46ade5b0f02b48115d148ce%2Fimage.png?alt=media" alt="Under a &#x22;Parser&#x22; header is a form with various fields, including &#x22;Has Header,&#x22; &#x22;Delimiter,&#x22; &#x22;Columns,&#x22; &#x22;Empty Values,&#x22; and more."><figcaption></figcaption></figure>

일반 구성 **Panther가 생성한** 섹션(위 스크린샷에 표시된 **스크립트 로그 파서(Script Log Parser)** 섹션 아래), 우리는 다음과 같이 필드를 정의합니다:

```yaml
필드:
- 이름: timestamp
  type: timestamp
  timeFormats: 
   - rfc3339
  isEventTime: true
  required: true
- 이름: action
  type: string
  required: true
- 이름: ip_address
  type: string
  indicators: [ip]
- name: message
  type: string
```

{% endtab %}

{% tab title="전체 YAML 표현" %}

```yaml
파서:
  csv:
    # CSV 파일은 다양한 형식이 있으며 각 행을 분리할 구분 문자(delimiter)를 선택할 수 있습니다
    delimiter: ","
    # 값 주변의 공백을 잘라냅니다
    공백제거: true
    # 'columns' 배열의 이름들은 각 행의 열에 매핑됩니다.
    # 열을 건너뛰려면 동일한 인덱스의 이름을 빈 문자열("")로 설정할 수 있습니다
    columns:
    - year
    - month
    - day
    - time
    - action
    - ip_address
    - message
    # 접두사로 시작하는 행(예: 주석)을 건너뜁니다
    skipPrefix: "# "
    # CSV 파일은 때때로 누락되었거나 해당 없음(N/A) 데이터를 위한 플레이스홀더 값을 사용합니다.
    # 'emptyValues'로 이러한 값을 정의하면 무시됩니다.
    emptyValues: ["-"]
    # 'expandFields' 지시문은 생성된 필드를 키/값 쌍에 주입하여 템플릿 문자열을 렌더링합니다
    expandFields:
      # 타임스탬프가 여러 열에 분리되어 있으므로 RFC3339 형식으로 다시 조립해야 합니다
      # 다음은 CSV 값에서 필드를 대체하여 'timestamp' 필드를 추가합니다
      timestamp: '%{year}-%{month}-%{day}T%{time}Z'
필드:
- 이름: timestamp
  type: timestamp
  timeFormats: 
   - rfc3339
  isEventTime: true
  required: true
- 이름: action
  type: string
  required: true
- 이름: ip_address
  type: string
  indicators: [ip]
- name: message
  type: string
```

{% endtab %}
{% endtabs %}

## 헤더가 있는 CSV 로그

헤더 행으로 시작하는 CSV 파일을 파싱하려면 두 가지 옵션이 있습니다:

* 헤더에 정의된 이름을 JSON 필드의 이름으로 사용
* 헤더를 무시하고 열 이름을 명시적으로 정의 [헤더 없는 CSV 파일에 대해 하는 것과 동일한 방식으로](#csv-logs-without-header)

{% hint style="warning" %}
CSV 파일에 헤더가 있고 열을 명시적으로 정의하지 않으면(대신 헤더에서 정의되도록 놔두는 경우), 이 스키마를 다른 스키마와 동일한 로그 소스(또는 단일 S3 접두사)에서 결합하지 마십시오. 그렇게 하면 로그가 잘못 분류될 수 있습니다.
{% endhint %}

헤더의 이름을 사용하려면 파서 설정은 다음과 같아야 합니다:

```yaml
파서:
  csv:
    delimiter: "," 
    # 'columns' 필드를 지정하지 않고 'hasHeader'를 true로 설정하면,
    # Panther는 헤더의 값에서 열 이름을 설정하라고 지시받습니다.
    hasHeader: true
    # 열 이름을 바꾸고 싶다면 'expandFields' 지시문을 사용할 수 있습니다
    expandFields:
      # 예를 들어 헤더에 '$cost'라는 열 이름이 있고 이를 'cost_us_dollars'로 정규화하려는 경우를 가정해 봅시다
      "cost_us_dollars": '%{$cost}'
```

헤더를 무시하고 열 이름 집합을 정의하려면 다음을 사용하세요:

```yaml
파서:
  csv:
    delimiter: "," 
    # 'columns' 필드를 지정하면서 'hasHeader'를 true로 설정하면, 
    # Panther는 헤더를 무시하고 'columns' 배열의 이름을 사용하도록 지시받습니다
    hasHeader: true
    columns:
    - foo
    - bar
    - baz
```
