# PRS 改版精要
- [Introduction](#introduction)
- [Problem](#problem)
- [Solution](#solution)
# introduction

此張圖為現行的 **Phone Reputation Service (PRS)** 的架構,
現在主要有兩種方式 query PRS,第一種就是當信件進入 Tmase engine 後,
會透過 [Parser 1](https://github.trendmicro.com/CoreTech-ERS/Library-TMASE/blob/d3c6a5a7eae17b3f494e063f54e10a5b83e55ed3/TMASE/src/tmase/CScamFilter.cpp#L439-L447) 去從 Email Body 中抓出並經過前處理後,將 extracted phone 丟到 Eureka 的 prs 參數中,去跟 pattern match 出 RID
第二種則是其他 Team(如 Trend Micro Check) 會直接透過 Eureka API post prs 這個參數來問。
而為了讓兩者去 match pattern 時候的格式是一致的,我們在 Eureka 裡面也做了一個 [Parser 2](https://adc.github.trendmicro.com/CoreTech-ERS/App-eureka/blob/master/internal/msgdecode/decoder.go#L277-L310) 去處理吃進來的 prs value
Tmase 跟 Eureka Parser 的範例如下
check prs 參數(處裡 prs 跟 senderinfo 兩個參數)
```go
// 示例1:原始字符串包含常用分隔符号,包含无效字符
rawString1 := "+1 (555) 123-4567"
processed1, err1 := preprocessPhoneNumber(rawString1)
// 输出:
// processed1 = "15551234567"
// err1 = nil
// 示例2:原始字符串不包含分隔符号,但以 0 开头
rawString2 := "0123456789"
processed2, err2 := preprocessPhoneNumber(rawString2)
// 输出:
// processed2 = "123456789"
// err2 = nil
// 示例3:原始字符串包含非数字字符
rawString3 := "1-800-Flowers"
processed3, err3 := preprocessPhoneNumber(rawString3)
// 输出:
// processed3 = ""
// err3 = Invalid char for phone number: -
// 示例4:原始字符串中的号码长度小于8
rawString4 := "1234567"
processed4, err4 := preprocessPhoneNumber(rawString4)
// 输出:
// processed4 = "1234567"
// err4 = Invalid length for phone number, too short: 1234567
// 示例5:原始字符串中的号码长度大于20
rawString5 := "123456789012345678901"
processed5, err5 := preprocessPhoneNumber(rawString5)
// 输出:
// processed5 = "123456789012345678901"
// err5 = Invalid length for phone number, too long: 123456789012345678901
```
如果出 error 則會[跳過](https://adc.github.trendmicro.com/CoreTech-ERS/App-eureka/blob/master/internal/msgdecode/decoder.go#L378-L381)
與此同時,透過 amps API 搜集 phone number 的 Parser 3,卻有著一些不太一樣的做法, 我們過去從眾多 [來源](https://adc.github.trendmicro.com/CoreTech-ERS/App-pyspark/tree/master/app/PRS2BuildSolution#prs-main-flow) 搜集 phone number,在 post 蒐集到的 phone number 以前,會先在 app-pyspark 做一些 [前處理](https://adc.github.trendmicro.com/CoreTech-ERS/App-pyspark/blob/master/app/PRSFmaSourcing/common.py#L63-L85) ,基本上處理邏輯跟 Parser 1、Parser 2 類似,就是把標點符號拿掉,並把開頭的 0 去掉。接著會把處理後的 phone number post 到 amps prs api,而在進 db 以前,還會經過一段分離 country code 跟 phone number 的 [function](https://adc.github.trendmicro.com/CoreTech-ERS/App-amps-webservice/blob/master/src/SenderPhoneReputationHandler.py#L200-L208)
amps api 分離 country code 跟 phone 的簡單圖示如下

# problem
1. Parser 不同步
由前例圖中可以得知,現階段我們各區域的 Parser 並沒有完全統一,例如一組電話號碼 `0912123123`,若是從 App-pyspark 輸入,就會被處理成 `912123123` 才打 amps api,最終存在 DB 的資料即為 `912123123`。但如果是直接打 amps api,則會在 DB 存成 `0912123123` 造成結果是,明明是同一筆電話號碼,卻會有兩種被存在 DB 的形式
2. Query data 跟 pattern data 不一樣(trimmed 0
如前述,經過 Eureka 處理後的電話號碼,會把最開頭的 0 給去掉,例如 `0912123123`,會變成 `912123123` 去跟 pattern mapping。但我們在出 Pattern 的時候,卻沒有把開頭的 0 拿掉,像是下方的 pattern data。這就會變成,明明有電話被紀錄在 DB,但最終經過 Eureka 後,卻會回一個沒 detect 的 RID
```
PRS pattern
08030172028,8.0
08064919823,8.0
08011337625,8.0
08067620627,8.0
```

3. Phone number hard to define if not E.164(+8869121231123)
- 現階段我們的 prs 分割 country code 跟 phone number 還是用自己的方式在處理的,而這種做法其實很容易有誤判,像是 `+1 242-555-0123` 的美國手機號碼,就會被我們判成 **Country Code:1242 phone :5550123**
- 如果非 E.164 格式,則難以界定該電話是哪一國的電話,像是我們在 prs-fma-sourcing 處理 phone number 去打 amps api 時候,有機會把這類的電話號碼的第一個 0 給去掉,造成問題二的現象。簡單來說,去掉 0 並沒有減少 FP 的發生,卻將 phone number 的一些資訊給去掉了,像是 `0912123123` 跟 `00912123123` 這兩個可能是不同國家的電話,卻可能在 DB 內都存成 `912123123`
# Solution
### TMASE
更改 extract 規則
### EUREKA
### APP-PYSPARK PHONE NUMBER COLLECT ETL
###
DNS prs ask
## 改動
## 改動前數據
## Good to have
##
#### 問題1
```
08090080406,8.0
08052500440,8.0
08064856158,8.0
09045743349,8.0
08075371143,8.0
09093243477,8.0
08061335270,8.0
08039213999,8.0
08067547313,8.0
09093807976,8.0
09053256421,8.0
```
這些東東 detect 不到
#### 原因
Eureka parser 會把 0 拿掉去 match
https://github.trendmicro.com/CoreTech-ERS/Library-TMASE/blob/d3c6a5a7eae17b3f494e063f54e10a5b83e55ed3/TMASE/src/tmase/CScamFilter.cpp#L439-L447
## Backward Compatibility
- Tmase
- Eureka
- RPS API
## Multiple Request Income
Other Request (FBN....)
- FBN
用這樣的方式去把這個處理
## 待處理問題
1. 沒有處理 ATTRIBUTE_MATCHING 這邊如果 prs 是空的該如何處理
2. Tmase Engine parser 改動
3. PRS 有一 ETL 是去找壞壞信,爬出裡面 body 有 phone 然後塞回 DB 的
https://adc.github.trendmicro.com/CoreTech-ERS/App-pyspark/blob/master/app/PRSHoneypotSourcing/prs_honeypot_sourcing.py#L134
但這 ETL 的作法,抓出來看 regex 的 email content 有很大機會碰到 base64 encoded 的 mail body,他好像沒有解開就去 regex match phone number 了(這樣當然啥都 match 不到?),看來我們 insert prs 的東東也沒認真 insert XDDD