收集 Fastly WAF 日志
支持的语言:
    
      
      
        
        
        
  
    
      Google SecOps
    
  
      
    
      
      
        
        
        
  
    
      SIEM
    
  
      
    
    
  概览
此解析器可从 Fastly WAF JSON 日志中提取字段,对其进行转换和重命名,然后将其映射到 UDM。它可处理各种数据类型、转换严重程度,并根据可用的 IP 和主机名信息对事件进行分类。它还会处理潜在的解析失败并舍弃格式错误的日志条目。
准备工作
确保您满足以下前提条件:
- Google SecOps 实例。
 - 有权配置 WAF 设置的 Fastly 账号。
 
设置 Feed
如需配置 Feed,请按以下步骤操作:
- 依次前往 SIEM 设置 > Feed。
 - 点击添加新 Feed。
 - 在下一页上,点击配置单个 Feed。
 - 在 Feed 名称字段中,输入 Feed 的名称(例如 Fastly WAF 日志)。
 - 选择 Webhook 作为来源类型。
 - 选择 Fastly WAF 作为日志类型。
 - 点击下一步。
 - 可选:为以下输入参数指定值:
- 拆分分隔符:用于分隔日志行的分隔符,例如 
\n。 
 - 拆分分隔符:用于分隔日志行的分隔符,例如 
 - 点击下一步。
 - 在最终确定界面中检查 Feed 配置,然后点击提交。
 - 点击生成密钥,生成用于对此 Feed 进行身份验证的密钥。
 - 复制并存储密钥。您将无法再次查看此密钥。如有需要,您可以重新生成新的 Secret 密钥,但此操作会使之前的 Secret 密钥失效。
 - 在详情标签页中,从端点信息字段复制 Feed 端点网址。您需要在客户端应用中指定此端点网址。
 - 点击完成。
 
为 Webhook Feed 创建 API 密钥
前往 Google Cloud 控制台 > 凭据。
点击创建凭据,然后选择 API 密钥。
将 API 密钥访问权限限制为 Google Security Operations API。
指定端点网址
- 在客户端应用中,指定 webhook Feed 中提供的 HTTPS 端点网址。
 通过在自定义标头中指定 API 密钥和密钥来启用身份验证,格式如下:
X-goog-api-key = API_KEY X-Webhook-Access-Key = SECRET建议:将 API 密钥指定为标头,而不是在网址中指定。
如果您的 Webhook 客户端不支持自定义标头,您可以使用以下格式的查询参数指定 API 密钥和密钥:
ENDPOINT_URL?key=API_KEY&secret=SECRET替换以下内容:
ENDPOINT_URL:Feed 端点网址。API_KEY:用于向 Google Security Operations 进行身份验证的 API 密钥。SECRET:您生成的用于验证 Feed 的密钥。
在 Fastly 中配置 webhook
- 登录 Fastly。
 - 可选:在网站菜单中选择一个网站(如果您有多个网站)。
 - 依次选择管理 > 网站集成。
 - 点击添加网站集成。
 - 选择 Generic Webhook。
 - Webhook 网址:输入 Google SecOps ENDPOINT_网址,然后输入 API_KEY 和 SECRET。
 - 提醒放置位置:选择所有活动或特定活动。
 - 可选:如果您选择了特定活动,请前往活动菜单,然后选择您希望 Webhook 发送的活动类型。
 - 点击创建网站集成。
 
UDM 映射表
| 日志字段 | UDM 映射 | 逻辑 | 
|---|---|---|
anomaly_score | 
security_result.detection_fields[].key: "anomaly"security_result.detection_fields[].value:  anomaly_score | 
如果 waf.score.anomaly 为 0 或空,且 anomaly_score 不为空或不为 0,则使用 anomaly_score 值填充 security_result.detection_fields 数组,键为“anomaly”,值为 anomaly_score 字段。 | 
cache_status | 
additional.fields[].key: "cache_status"additional.fields[].value.string_value: cache_status | 
cache_status 值用于填充 additional.fields 数组,该数组的键为“cache_status”,值为 cache_status 字段。 | 
client_ip | 
principal.ip:client_ip | 
client_ip 字段已映射到 principal.ip。 | 
connection.fastly_is_edge | 
additional.fields[].key: "fastly_is_edge"additional.fields[].value.bool_value: connection.fastly_is_edge | 
connection.fastly_is_edge 值用于填充 additional.fields 数组,该数组的键为“fastly_is_edge”,值为 connection.fastly_is_edge 字段的值。 | 
connection.fastly_is_shield | 
additional.fields[].key: "fastly_is_shield"additional.fields[].value.bool_value: connection.fastly_is_shield | 
connection.fastly_is_shield 值用于填充 additional.fields 数组,该数组的键为“fastly_is_shield”,值为 connection.fastly_is_shield 字段的值。 | 
connection.request_tls_version | 
network.tls.version:connection.request_tls_version | 
connection.request_tls_version 字段已映射到 network.tls.version。 | 
fastly.server | 
target.hostname:fastly.server | 
fastly.server 字段已映射到 target.hostname。 | 
fastly.service_id | 
additional.fields[].key: "service_id"additional.fields[].value.string_value: fastly.service_id | 
fastly.service_id 值用于填充 additional.fields 数组,该数组的键为“service_id”,值为 fastly.service_id 字段。 | 
geo.city | 
principal.location.city:geo.city | 
geo.city 字段已映射到 principal.location.city。 | 
geo.country | 
principal.location.country_or_region:geo.country | 
geo.country 字段已映射到 principal.location.country_or_region。 | 
geo.location | 
principal.location.region_latitude:从 geo.location 中提取principal.location.region_longitude:从 geo.location 中提取 | 
使用正则表达式从 geo.location 字段中提取经度和纬度,并分别映射到 principal.location.region_latitude 和 principal.location.region_longitude。 | 
geo.region | 
principal.location.state:geo.region | 
geo.region 字段已映射到 principal.location.state。 | 
host | 
principal.hostname:host | 
host 字段已映射到 principal.hostname。 | 
request_headers.accept_charset | 
additional.fields[].key: "accept_charset"additional.fields[].value.string_value: request_headers.accept_charset | 
request_headers.accept_charset 值用于填充 additional.fields 数组,该数组的键为“accept_charset”,值为 request_headers.accept_charset 字段。 | 
request_headers.accept_language | 
additional.fields[].key: "accept_language"additional.fields[].value.string_value: request_headers.accept_language | 
request_headers.accept_language 值用于填充 additional.fields 数组,该数组的键为“accept_language”,值为 request_headers.accept_language 字段。 | 
request_headers.referer | 
network.http.referral_url:request_headers.referer | 
request_headers.referer 字段已映射到 network.http.referral_url。 | 
request_headers.user_agent | 
network.http.user_agent:request_headers.user_agent | 
request_headers.user_agent 字段已映射到 network.http.user_agent。 | 
request_id | 
metadata.product_log_id:request_id | 
request_id 字段已映射到 metadata.product_log_id。 | 
request_method | 
network.http.method:request_method | 
request_method 字段已映射到 network.http.method。 | 
response_headers.cache_control | 
additional.fields[].key: "cache_control"additional.fields[].value.string_value: response_headers.cache_control | 
response_headers.cache_control 值用于填充 additional.fields 数组,其中包含“cache_control”键和 response_headers.cache_control 字段的值。 | 
response_headers.content_type | 
additional.fields[].key: "content_type"additional.fields[].value.string_value: response_headers.content_type | 
response_headers.content_type 值用于填充 additional.fields 数组,该数组的键为“content_type”,值为 response_headers.content_type 字段。 | 
response_state | 
additional.fields[].key: "response_state"additional.fields[].value.string_value: response_state | 
response_state 值用于填充 additional.fields 数组,该数组的键为“response_state”,值为 response_state 字段的值。 | 
response_status | 
network.http.response_code:response_status | 
如果 status 字段为空,则 response_status 字段会映射到 network.http.response_code。 | 
rule_id | 
security_result.rule_id:rule_id | 
如果 waf.rule_id 为空,则使用 rule_id 值填充 security_result.rule_id。 | 
severity | 
waf.severity:severity | 
severity 字段值会复制到 waf.severity。 | 
size_bytes.request_header | 
network.sent_bytes:size_bytes.request_header | 
size_bytes.request_header 字段已映射到 network.sent_bytes。 | 
size_bytes.response_header | 
network.received_bytes:size_bytes.response_header | 
size_bytes.response_header 字段已映射到 network.received_bytes。 | 
status | 
network.http.response_code:status | 
status 字段已映射到 network.http.response_code。 | 
timestamp | 
metadata.event_timestamp:timestamp | 
系统会解析 timestamp 字段并将其映射到 metadata.event_timestamp。 | 
url | 
target.url:url | 
url 字段已映射到 target.url。 | 
waf.blocked | 
security_result.action:派生 | 
如果 waf.blocked 为 false,则将 security_result.action 设置为“ALLOW”。如果 waf.blocked 为 true,则将 security_result.action 设置为“BLOCK”。 | 
waf.executed | 
security_result.detection_fields[].key: "executed"security_result.detection_fields[].value: waf.executed | 
waf.executed 值用于填充 security_result.detection_fields 数组,其中包含一个键“executed”和 waf.executed 字段的值。 | 
waf.failures | 
security_result.detection_fields[].key: "failures"security_result.detection_fields[].value: waf.failures | 
waf.failures 值用于填充 security_result.detection_fields 数组,该数组的键为“failures”,值为 waf.failures 字段。 | 
waf.logged | 
security_result.detection_fields[].key: "logged"security_result.detection_fields[].value: waf.logged | 
waf.logged 值用于填充 security_result.detection_fields 数组,其中包含键“logged”和 waf.logged 字段的值。 | 
waf.message | 
metadata.description:waf.message | 
如果 waf.message 不为空,则会映射到 metadata.description。 | 
waf.rule_id | 
security_result.rule_id:waf.rule_id | 
如果 waf.rule_id 不为空,则会映射到 security_result.rule_id。 | 
waf.score.anomaly | 
security_result.detection_fields[].key: "anomaly"security_result.detection_fields[].value: waf.score.anomaly | 
如果 waf.score.anomaly 不为 0 且不为空,则该值用于填充 security_result.detection_fields 数组,其中键为“anomaly”,值为 waf.score.anomaly 字段。 | 
waf.score.http_violation | 
security_result.detection_fields[].key: "http_violation"security_result.detection_fields[].value: waf.score.http_violation | 
如果 waf.score.http_violation 不为 0 且不为空,则该值用于填充 security_result.detection_fields 数组。 | 
waf.score.lfi | 
security_result.detection_fields[].key: "lfi"security_result.detection_fields[].value: waf.score.lfi | 
与 waf.score.http_violation 类似的逻辑。 | 
waf.score.php_injection | 
security_result.detection_fields[].key: "php_injection"security_result.detection_fields[].value: waf.score.php_injection | 
与 waf.score.http_violation 类似的逻辑。 | 
waf.score.rce | 
security_result.detection_fields[].key: "rce"security_result.detection_fields[].value: waf.score.rce | 
与 waf.score.http_violation 类似的逻辑。 | 
waf.score.rfi | 
security_result.detection_fields[].key: "rfi"security_result.detection_fields[].value: waf.score.rfi | 
与 waf.score.http_violation 类似的逻辑。 | 
waf.score.session_fixation | 
security_result.detection_fields[].key: "session_fixation"security_result.detection_fields[].value: waf.score.session_fixation | 
与 waf.score.http_violation 类似的逻辑。 | 
waf.score.sql_injection | 
security_result.detection_fields[].key: "sql_injection"security_result.detection_fields[].value: waf.score.sql_injection | 
与 waf.score.http_violation 类似的逻辑。 | 
waf.score.xss | 
security_result.detection_fields[].key: "xss"security_result.detection_fields[].value: waf.score.xss | 
与 waf.score.http_violation 类似的逻辑。 | 
waf.severity | 
security_result.severity:派生security_result.severity_details:waf.severity | 
如果 waf.severity 不为空,则根据范围确定 security_result.severity 的值(<=3:HIGH,>3 且 <=6:MEDIUM,>6 且 <=8:LOW,否则:UNKNOWN_SEVERITY)。原始 waf.severity 值也会映射到 security_result.severity_details。 | 
waf_message | 
metadata.description:waf_message | 
如果 waf.message 为空,但 waf_message 不为空,则会映射到 metadata.description。如果 client_ip 或 host 和 fastly.server 不为空,则将 metadata.event_type 设置为“NETWORK_HTTP”。否则,如果 client_ip 或 host 不为空,则将 metadata.event_type 设置为“STATUS_UPDATE”。否则,该值会设置为“GENERIC_EVENT”。硬编码的值。硬编码的值。硬编码的值。 | 
需要更多帮助?从社区成员和 Google SecOps 专业人士那里获得解答。