# 정규식 로그 파서

## 개요

구조가 더 복잡한 텍스트 로그 유형의 경우, 다음을 사용할 수 있습니다 `regex` 파서.

사용자를 사용할 것이며, `regex` 파서는 정규 표현식의 명명된 그룹을 사용하여 각 텍스트 줄에서 필드 값을 추출합니다. grok 구문(예: `%{PATTERN_NAME:field_name}`)을 사용하여 Panther가 제공하는 내장 패턴을 활용하거나 직접 정의한 패턴을 사용해 복잡한 표현식을 구성할 수 있습니다.

{% hint style="warning" %}
Panther의 로그 프로세서는 [`RE2` 구문](https://github.com/google/re2/wiki/Syntax) 을(를) 정규 표현식에 사용합니다. `RE2` 는 다른 정규 표현식 엔진에서 일반적인 일부 연산(예: `lookbehind`)을 지원하지 않습니다. 다른 시스템에서 복사/붙여넣기한 표현식이나 grok 패턴을 사용할 때는 반드시 확인하세요.
{% endhint %}

예를 들어 다음 텍스트와 매치하려면

```
2020-10-10T14:32:05 [FOO_SERVICE@127.0.0.1] [DEBUG] "" Something when wrong
```

다음 패턴으로 이 grok 구문을 사용할 수 있습니다:

```
%{NOTSPACE:timestamp} \[%{WORD:service}@%{DATA:ip}\] \[%{WORD:log_level}\] %{GREEDYDATA:message}
```

이는 대략 다음 '원시' 정규식과 동일합니다:

```
(?P<timestamp>\S+) \[(?P<service>\w+)@(?P<ip>.*?)\] \[(?P<log_level>\w+)\] (?P<message>.*)
```

{% hint style="info" %}
최상의 성능을 위해 다음과 같은 단순한 내장 패턴을 사용하세요: `DATA`, `NOTSPACE`, `GREEDYDATA` 와 `WORD`값에 따라 필드 이름을 구분해야 하는 경우(예: `(%{IP:ip_address}|%{WORD:username})`
{% endhint %}

## 정규식을 사용하는 예

다음을 사용하여 `regex` 파서를 사용해 로그 유형을 정의하겠습니다 `Juniper.Audit` 로그. Panther는 이미 [이 로그들을 네이티브로 지원합니다](https://docs.panther.com/ko/supported-logs/juniper#juniper.audit)그러나 여기서는 형식이 가변적이고 충돌하는 형태를 가지며 오직 `regex` 파서.

을(를) 사용해야만 '해결'될 수 있기 때문에 이들을 사용합니다. `Juniper.Audit` 의 샘플 로그는 다음과 같습니다:

```
Jan 22 16:14:23 my-jwas [mws-audit][INFO] [mykonos] [10.10.0.117] Logged in successfully
Jan 23 19:16:22 my-jwas [mws-audit][INFO] [ea77722a8516b0d1135abb19b1982852] Deactivate response 1832840420318015488
Feb 7 20:29:51 my-jwas [mws-audit][INFO] [mykonos] [10.10.0.113] Login failed. Attempt: 1
Feb 14 19:02:54 my-jwas [mws-audit][INFO][mykonos] Changed configuration parameters: services.spotlight.enabled, services.spotlight.server_address
```

다음은 이러한 로그에 대해 `regex`:

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

<figure><img src="https://2400888838-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LgdiSWdyJcXPahGi9Rs-2910905616%2Fuploads%2Fgit-blob-235e41eb1220881fb86dd387a07c90d56df1153e%2Fimage.png?alt=media" alt="In a &#x22;Schema&#x22; section, &#x22;Regex&#x22; is selected for a Parser field. There are various form fields shown, such as Pattern Definitions, Match Patterns, and Empty Values."><figcaption></figcaption></figure>

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

```yaml
필드:
- 이름: timestamp
  type: timestamp
  required: true
  timeFormats: 
   - '%b %d %H:%M:%S'
  isEventTime: false # 타임스탬프에 연도가 없으므로 파티션 시간으로 사용할 수 없습니다
- 이름: log_level
  type: string
  required: true
- name: apikey
  type: string
- 이름: username
  type: string
- name: request_ip
  type: string
  indicators: [ip]
- name: message
  type: string
```

{% endtab %}

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

```yaml
파서:
  regex:
    patternDefinitions:
      JUNIPER_TIMESTAMP: '[A-Z][a-z]{2} \d?\d \d\d:\d\d:\d\d'
      # apikey는 32개의 16진수 문자로 구성됩니다
      API_KEY: '[a-fA-F0-9]{32}'
    # 앞으로 디버깅에 도움이 되도록 패턴을 여러 부분으로 분할하겠습니다.
    # 모든 부분은 Panther에 의해 공백을 추가하지 않고 단일 패턴으로 연결됩니다.
    # 패턴을 분할하고 싶지 않다면 단일 문자열 배열을 사용하면 됩니다.
    매치:
    # 로그 줄은 타임스탬프로 시작합니다( 'timestamp'로 캡처됨)
    - '^%{JUNIPER_TIMESTAMP:timestamp}'
    # 그다음 이 고정 텍스트가 옵니다
    - ' my-jwas \[mws-audit\]'
    # 그런 다음 대괄호로 둘러싸인 로그 레벨과 선택적 공백이 옵니다( 'log_level'로 캡처됨)
    - '\[%{DATA:log_level}\] ?' 
    # 그 이후에는 대괄호로 둘러싸인 api 키 또는 사용자 이름이 오며,
    # 매치에 따라 'apikey' 또는 'username'으로 캡처됩니다
    - '\[(%{API_KEY:apikey}|%{USERNAME:username})\] '
    # 선택적으로 요청의 IP 주소가 대괄호로 따라올 수 있습니다( 'request_ip'로 캡처됨)
    # 특정 'IP' 명명 패턴 대신 'DATA'를 사용하는 점에 유의하세요. 
    # 'request_ip'는 항상 이 위치에 있고 로그 유형 매치가
    # 구별되는 ' my-jwas [mws-audit]' 리터럴 때문에 확실하므로 필요하지 않습니다.
    - '(\[%{DATA:request_ip}\])?'
    # 마지막으로 줄의 나머지는 메시지입니다( 'message'로 캡처됨)
    - '%{GREEDYDATA:message}'
    trimSpace: true # 메시지의 공백을 잘라내고 싶습니다
필드:
- 이름: timestamp
  type: timestamp
  required: true
  timeFormats: 
   - '%b %d %H:%M:%S'
  isEventTime: false # 타임스탬프에 연도가 없으므로 파티션 시간으로 사용할 수 없습니다
- 이름: log_level
  type: string
  required: true
- name: apikey
  type: string
- 이름: username
  type: string
- name: request_ip
  type: string
  indicators: [ip]
- name: message
  type: string
```

{% endtab %}
{% endtabs %}

## 내장 정규식 패턴 참조

다음 표는 사용 가능한 Panther 내장 정규식 패턴을 자세히 설명합니다.

### 일반

<table><thead><tr><th width="173">이름</th><th>정규식(Regex)</th></tr></thead><tbody><tr><td><code>DATA</code></td><td><code>.*?</code></td></tr><tr><td><code>GREEDYDATA</code></td><td><code>.*</code></td></tr><tr><td><code>NOTSPACE</code></td><td><code>\S+</code></td></tr><tr><td><code>SPACE</code></td><td><code>\s*</code></td></tr><tr><td><code>WORD</code></td><td><code>\b\w+\b</code></td></tr><tr><td><code>QUOTEDSTRING</code></td><td><code>"(?:\.|[^\"]+)+"|""|'(?:\.|[^\']+)+'|''</code></td></tr><tr><td><code>HEXDIGIT</code></td><td><code>[0-9a-fAF]</code></td></tr><tr><td><code>UUID</code></td><td><code>%{HEXDIGIT}{8}-(?:%{HEXDIGIT}{4}-){3}%{HEXDIGIT}{12}</code></td></tr></tbody></table>

### 숫자

<table><thead><tr><th width="153">이름</th><th>정규식(Regex)</th></tr></thead><tbody><tr><td><code>INT</code></td><td><code>[+-]?(?:[0-9]+)</code></td></tr><tr><td><code>BASE10NUM</code></td><td><code>[+-]?(?:[0-9]+(?:.[0-9]+)?)|.[0-9]+</code></td></tr><tr><td><code>NUMBER</code></td><td><code>%{BASE10NUM}</code></td></tr><tr><td><code>BASE16NUM</code></td><td><code>(?:0[xX])?%{HEXDIGIT}+</code></td></tr><tr><td><code>POSINT</code></td><td><code>\b[1-9][0-9]*\b</code></td></tr><tr><td><code>NONNEGINT</code></td><td><code>\b[0-9]+\b</code></td></tr></tbody></table>

### 네트워크

<table><thead><tr><th width="154">이름</th><th>정규식(Regex)</th></tr></thead><tbody><tr><td><code>CISCOMAC</code></td><td><code>(?:[A-Fa-f0-9]{4}.){2}[A-Fa-f0-9]{4}</code></td></tr><tr><td><code>WINDOWSMAC</code></td><td><code>(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2}</code></td></tr><tr><td><code>COMMONMAC</code></td><td><code>(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}</code></td></tr><tr><td><code>MAC</code></td><td><code>%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC}</code></td></tr><tr><td><code>IPV6</code></td><td><code>\b(?:(?:(?:%{HEXDIGIT}{1,4}:){7}(?:%{HEXDIGIT}{1,4}|:))|(?:(?:%{HEXDIGIT}{1,4}:){6}(?::%{HEXDIGIT}{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:%{HEXDIGIT}{1,4}:){5}(?:(?:(?::%{HEXDIGIT}{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|((%{HEXDIGIT}{1,4}:){4}(((:%{HEXDIGIT}{1,4}){1,3})|((:%{HEXDIGIT}{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|((%{HEXDIGIT}{1,4}:){3}(((:%{HEXDIGIT}{1,4}){1,4})|((:%{HEXDIGIT}{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|((%{HEXDIGIT}{1,4}:){2}(((:%{HEXDIGIT}{1,4}){1,5})|((:%{HEXDIGIT}{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|((%{HEXDIGIT}{1,4}:){1}(((:%{HEXDIGIT}{1,4}){1,6})|((:%{HEXDIGIT}{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:%{HEXDIGIT}{1,4}){1,7})|((:%{HEXDIGIT}{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\b</code></td></tr><tr><td><code>IPV4INT</code></td><td><code>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9]</code></td></tr><tr><td><code>IPV4</code></td><td><code>\b(?:(?:%{IPV4INT}).){3}(?:%{IPV4INT})\b</code></td></tr><tr><td><code>IP</code></td><td><code>%{IPV6}|%{IPV4}</code></td></tr><tr><td><code>HOSTNAME</code></td><td><code>\b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(.?|\b)</code></td></tr><tr><td><code>IPORHOST</code></td><td><code>%{IP}|%{HOSTNAME}</code></td></tr><tr><td><code>HOSTPORT</code></td><td><code>%{IPORHOST}:%{POSINT}</code></td></tr></tbody></table>

### URI

<table><thead><tr><th width="177">이름</th><th>정규식(Regex)</th></tr></thead><tbody><tr><td><code>USERNAME</code></td><td><code>[a-zA-Z0-9._-]+</code></td></tr><tr><td><code>UNIXPATH</code></td><td><code>(?:/[\w_%!$@:.,-]?/?)(\S+)?</code></td></tr><tr><td><code>WINPATH</code></td><td><code>(?:[A-Za-z]:|\)(?:\[^\?])+</code></td></tr><tr><td><code>PATH</code></td><td><code>(?:%{UNIXPATH}|%{WINPATH})</code></td></tr><tr><td><code>TTY</code></td><td><code>(?:/dev/(pts|tty([pq])?)(\w+)?/?(?:[0-9]+))</code></td></tr><tr><td><code>URIPROTO</code></td><td><code>[A-Za-z]+(?:+[A-Za-z+]+)?</code></td></tr><tr><td><code>URIHOST</code></td><td><code>%{IPORHOST}(?::%{POSINT})?</code></td></tr><tr><td><code>URIPATH</code></td><td><code>(?:/[A-Za-z0-9$.+!*'(){},~:;=@#%_-]*)+</code></td></tr><tr><td><code>URIPARAM</code></td><td><code>?[A-Za-z0-9$.+!*'|(){},~@#%&#x26;/=:;_?-[]&#x3C;>]*</code></td></tr><tr><td><code>URIPATHPARAM</code></td><td><code>%{URIPATH}(?:%{URIPARAM})?</code></td></tr><tr><td><code>URI</code></td><td><code>%{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})?</code></td></tr></tbody></table>

### 타임스탬프

<table><thead><tr><th width="236">이름</th><th>정규식(Regex)</th></tr></thead><tbody><tr><td><code>MONTH</code></td><td><code>\b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|June?|July?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\b MONTHNUM 0?[1-9]|1[0-2]</code></td></tr><tr><td><code>MONTHNUM</code></td><td><code>0?[1-9]|1[0-2]</code></td></tr><tr><td><code>MONTHNUM2</code></td><td><code>0[1-9]|1[0-2]</code></td></tr><tr><td><code>MONTHDAY</code></td><td><code>(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9]</code></td></tr><tr><td><code>DAY</code></td><td><code>\b(?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?)\b</code></td></tr><tr><td><code>YEAR</code></td><td><code>(?:\d\d){1,2}</code></td></tr><tr><td><code>HOUR</code></td><td><code>2[0123]|[01]?[0-9]</code></td></tr><tr><td><code>MINUTE</code></td><td><code>[0-5][0-9]</code></td></tr><tr><td><code>SECOND</code></td><td><code>(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?</code></td></tr><tr><td><code>KITCHEN</code></td><td><code>%{HOUR}:%{MINUTE}</code></td></tr><tr><td><code>TIME</code></td><td><code>%{HOUR}:%{MINUTE}:%{SECOND}</code></td></tr><tr><td><code>DATE_US</code></td><td><code>%{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR}</code></td></tr><tr><td><code>DATE_EU</code></td><td><code>%{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR}</code></td></tr><tr><td><code>ISO8601_TIMEZONE</code></td><td><code>(?:Z|[+-]%{HOUR}(?::?%{MINUTE}))</code></td></tr><tr><td><code>ISO8601_SECOND</code></td><td><code>(?:%{SECOND}|60)</code></td></tr><tr><td><code>TIMESTAMP_ISO8601</code></td><td><code>%{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?</code></td></tr><tr><td><code>DATE</code></td><td><code>%{DATE_US}|%{DATE_EU}</code></td></tr><tr><td><code>DATETIME</code></td><td><code>%{DATE}[- ]%{TIME}</code></td></tr><tr><td><code>TZ</code></td><td><code>[A-Z]{3}</code></td></tr><tr><td><code>TZOFFSET</code></td><td><code>[+-]\d{4}</code></td></tr><tr><td><code>TIMESTAMP_RFC822</code></td><td><code>%{DAY} %{MONTH} %{MONTHDAY} %{YEAR} %{TIME} %{TZ}</code></td></tr><tr><td><code>TIMESTAMP_RFC2822</code></td><td><code>%{DAY}, %{MONTHDAY} %{MONTH} %{YEAR} %{TIME} %{ISO8601_TIMEZONE}</code></td></tr><tr><td><code>TIMESTAMP_OTHER</code></td><td><code>%{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{TZ} %{YEAR}</code></td></tr><tr><td><code>TIMESTAMP_EVENTLOG</code></td><td><code>%{YEAR}%{MONTHNUM2}%{MONTHDAY}%{HOUR}%{MINUTE}%{SECOND}</code></td></tr><tr><td><code>SYSLOGTIMESTAMP</code></td><td><code>%{MONTH} +%{MONTHDAY} %{TIME}</code></td></tr><tr><td><code>HTTPDATE</code></td><td><code>%{MONTHDAY}/%{MONTH}/%{YEAR}:%{TIME} %{TZOFFSET}</code></td></tr></tbody></table>

### 별칭

<table><thead><tr><th width="134">이름</th><th>동등 항목</th></tr></thead><tbody><tr><td><code>NS</code></td><td><code>NOTSPACE</code></td></tr><tr><td><code>QS</code></td><td><code>QUOTEDSTRING</code></td></tr><tr><td><code>HOST</code></td><td><code>HOSTNAME</code></td></tr><tr><td><code>PID</code></td><td><code>POSINT</code></td></tr><tr><td><code>USER</code></td><td><code>USERNAME</code></td></tr></tbody></table>
