Skip to content

Commit 6b8b970

Browse files
constanca-matoulme
andauthored
Add log record attributes from category from FrontDoorWebApplicationFirewallLog (#39994)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Same as done before for Azure CDN Access Log: #39820. Remove the fields from category FrontDoorWebApplicationFirewallLog from the body log record and place them as log record attributes. See a detailed description in #39993. <!-- Issue number (e.g. #1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes #39993. <!--Describe what testing was performed and which tests were added.--> #### Testing Unit tests added. <!--Describe the documentation added.--> #### Documentation README updated. <!--Please delete paragraphs that you did not use before submitting.--> --------- Co-authored-by: Antoine Toulme <[email protected]>
1 parent 4dff345 commit 6b8b970

File tree

10 files changed

+244
-95
lines changed

10 files changed

+244
-95
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: breaking
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: pkg
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Remove the fields from category FrontDoorWebApplicationFirewallLog from the body log record and place them as log record attributes.
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [39993]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

pkg/translator/azurelogs/README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,22 @@ The mapping for this category is as follows:
3232
| `ErrorInfo` | Same as `errorInfo` |
3333
| `endpoint` | Either:<br>1. `destination.address` if it is equal to `backendHostname`<br>2. `network.peer.address` otherwise. |
3434
| `isReceivedFromClient` | `network.io.direction`<br>- If `true`, `receive`<br>- Else, `transmit` |
35-
| `backendHostname` | 1. `destination.address` <br>2. `destination.port`, if any |
35+
| `backendHostname` | 1. `destination.address` <br>2. `destination.port`, if any |
36+
37+
38+
### Front Door Web Application Firewall Logs
39+
40+
The mapping for this category is as follows:
41+
42+
| Original Field (JSON) | Log Record Attribute |
43+
|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------|
44+
| `clientIP` | `client.address` |
45+
| `clientPort` | `client.port` |
46+
| `socketIP` | `source.address` |
47+
| `requestUri` | `url.orginal`<br>Also parses it to get fields:<br>1.`url.scheme`<br>2.`url.fragment`<br>3.`url.query`<br>4.`url.path`<br>5.`url.port` |
48+
| `ruleName` | `azure.frontdoor.waf.rule.name` |
49+
| `policy` | `azure.frontdoor.waf.policy.name` |
50+
| `action` | `azure.frontdoor.waf.action` |
51+
| `host` | `http.request.header.host` |
52+
| `trackingReference` | `azure.ref` |
53+
| `policyMode` | `azure.frontdoor.waf.policy.mode` |

pkg/translator/azurelogs/category_logs.go

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const (
2222
categoryAzureCdnAccessLog = "AzureCdnAccessLog"
2323
categoryFrontDoorAccessLog = "FrontDoorAccessLog"
2424
categoryFrontDoorHealthProbeLog = "FrontDoorHealthProbeLog"
25-
categoryFrontdoorWebApplicationFirewallLog = "FrontdoorWebApplicationFirewallLog"
25+
categoryFrontdoorWebApplicationFirewallLog = "FrontDoorWebApplicationFirewallLog"
2626
categoryAppServiceAppLogs = "AppServiceAppLogs"
2727
categoryAppServiceAuditLogs = "AppServiceAuditLogs"
2828
categoryAppServiceAuthenticationLogs = "AppServiceAuthenticationLogs"
@@ -59,6 +59,25 @@ const (
5959
missingPort = "missing port in address"
6060
)
6161

62+
const (
63+
// azure front door WAF attributes
64+
65+
// attributeAzureFrontDoorWAFRuleName holds the name of the WAF rule that
66+
// the request matched.
67+
attributeAzureFrontDoorWAFRuleName = "azure.frontdoor.waf.rule.name"
68+
69+
// attributeAzureFrontDoorWAFPolicyName holds the name of the WAF policy
70+
// that processed the request.
71+
attributeAzureFrontDoorWAFPolicyName = "azure.frontdoor.waf.policy.name"
72+
73+
// attributeAzureFrontDoorWAFPolicyMode holds the operations mode of the
74+
// WAF policy.
75+
attributeAzureFrontDoorWAFPolicyMode = "azure.frontdoor.waf.policy.mode"
76+
77+
// attributeAzureFrontDoorWAFAction holds the action taken on the request.
78+
attributeAzureFrontDoorWAFAction = "azure.frontdoor.waf.action"
79+
)
80+
6281
var (
6382
errStillToImplement = errors.New("still to implement")
6483
errUnsupportedCategory = errors.New("category not supported")
@@ -351,11 +370,46 @@ func addFrontDoorHealthProbeLogProperties(_ []byte, _ plog.LogRecord) error {
351370
return errStillToImplement
352371
}
353372

373+
// See https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/waf-front-door-monitor?pivots=front-door-standard-premium#waf-logs
374+
type frontDoorWAFLogProperties struct {
375+
ClientIP string `json:"clientIP"`
376+
ClientPort string `json:"clientPort"`
377+
SocketIP string `json:"socketIP"`
378+
RequestURI string `json:"requestUri"`
379+
RuleName string `json:"ruleName"`
380+
Policy string `json:"policy"`
381+
Action string `json:"action"`
382+
Host string `json:"host"`
383+
TrackingReference string `json:"trackingReference"`
384+
PolicyMode string `json:"policyMode"`
385+
}
386+
354387
// addFrontDoorWAFLogProperties parses the Front Door access log, and adds
355388
// the relevant attributes to the record
356-
func addFrontDoorWAFLogProperties(_ []byte, _ plog.LogRecord) error {
357-
// TODO @constanca-m implement this the same way as addAzureCdnAccessLogProperties
358-
return errStillToImplement
389+
func addFrontDoorWAFLogProperties(data []byte, record plog.LogRecord) error {
390+
var properties frontDoorWAFLogProperties
391+
if err := gojson.Unmarshal(data, &properties); err != nil {
392+
return fmt.Errorf("failed to parse AzureCdnAccessLog properties: %w", err)
393+
}
394+
395+
if err := putInt(string(conventions.ClientPortKey), properties.ClientPort, record); err != nil {
396+
return err
397+
}
398+
399+
if err := addRequestURIProperties(properties.RequestURI, record); err != nil {
400+
return fmt.Errorf(`failed to handle "requestUri" field: %w`, err)
401+
}
402+
403+
putStr(string(conventions.ClientAddressKey), properties.ClientIP, record)
404+
putStr(string(conventions.SourceAddressKey), properties.SocketIP, record)
405+
putStr(attributeAzureRef, properties.TrackingReference, record)
406+
putStr("http.request.header.host", properties.Host, record)
407+
putStr(attributeAzureFrontDoorWAFPolicyName, properties.Policy, record)
408+
putStr(attributeAzureFrontDoorWAFPolicyMode, properties.PolicyMode, record)
409+
putStr(attributeAzureFrontDoorWAFRuleName, properties.RuleName, record)
410+
putStr(attributeAzureFrontDoorWAFAction, properties.Action, record)
411+
412+
return nil
359413
}
360414

361415
// addAppServiceAppLogsProperties parses the App Service access log, and adds

pkg/translator/azurelogs/property_names.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -102,25 +102,6 @@ func handleFrontDoorHealthProbeLog(field string, value any, attrs map[string]any
102102
}
103103
}
104104

105-
func handleFrontdoorWebApplicationFirewallLog(field string, value any, attrs map[string]any, attrsProps map[string]any) {
106-
switch field {
107-
case "clientIP":
108-
attrs["client.address"] = value
109-
case "clientPort":
110-
attrs["client.port"] = value
111-
case "socketIP":
112-
attrs[string(conventions.NetworkPeerAddressKey)] = value
113-
case "requestUri":
114-
attrs[string(conventions.URLFullKey)] = value
115-
case "host":
116-
attrs[string(conventions.ServerAddressKey)] = value
117-
case "trackingReference":
118-
attrs[string(conventions.AzServiceRequestIDKey)] = value
119-
default:
120-
attrsProps[field] = value
121-
}
122-
}
123-
124105
func handleAppServiceAppLogs(field string, value any, attrs map[string]any, attrsProps map[string]any) {
125106
switch field {
126107
case "ContainerId":

pkg/translator/azurelogs/resourcelogs_to_logs.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,6 @@ func copyPropertiesAndApplySemanticConventions(category string, properties []byt
282282
handleFunc = handleFrontDoorAccessLog
283283
case categoryFrontDoorHealthProbeLog:
284284
handleFunc = handleFrontDoorHealthProbeLog
285-
case categoryFrontdoorWebApplicationFirewallLog:
286-
handleFunc = handleFrontdoorWebApplicationFirewallLog
287285
case categoryAppServiceAppLogs:
288286
handleFunc = handleAppServiceAppLogs
289287
case categoryAppServiceAuditLogs:

pkg/translator/azurelogs/resourcelogs_to_logs_test.go

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,47 @@ func TestUnmarshalLogs_AzureCdnAccessLog(t *testing.T) {
318318
}
319319
}
320320

321+
func TestUnmarshalLogs_FrontDoorWebApplicationFirewallLog(t *testing.T) {
322+
t.Parallel()
323+
324+
dir := "testdata/frontdoorwebapplicationfirewalllog"
325+
tests := map[string]struct {
326+
logFilename string
327+
expectedFilename string
328+
expectsErr string
329+
}{
330+
"valid_1": {
331+
logFilename: "valid_1.json",
332+
expectedFilename: "valid_1_expected.yaml",
333+
},
334+
}
335+
336+
u := &ResourceLogsUnmarshaler{
337+
Version: testBuildInfo.Version,
338+
Logger: zap.NewNop(),
339+
}
340+
341+
for name, test := range tests {
342+
t.Run(name, func(t *testing.T) {
343+
data, err := os.ReadFile(filepath.Join(dir, test.logFilename))
344+
require.NoError(t, err)
345+
346+
logs, err := u.UnmarshalLogs(data)
347+
348+
if test.expectsErr != "" {
349+
require.ErrorContains(t, err, test.expectsErr)
350+
return
351+
}
352+
353+
require.NoError(t, err)
354+
355+
expectedLogs, err := golden.ReadLogs(filepath.Join(dir, test.expectedFilename))
356+
require.NoError(t, err)
357+
require.NoError(t, plogtest.CompareLogs(expectedLogs, logs, plogtest.IgnoreResourceLogsOrder()))
358+
})
359+
}
360+
}
361+
321362
func TestUnmarshalLogs_Files(t *testing.T) {
322363
// TODO @constanca-m Eventually this test function will be fully
323364
// replaced with TestUnmarshalLogs_<category>, once all the currently supported
@@ -363,10 +404,6 @@ func TestUnmarshalLogs_Files(t *testing.T) {
363404
logFilename: "log-frontdoorhealthprobelog.json",
364405
expectedFilename: "front-door-health-probe-log-expected.yaml",
365406
},
366-
"front_door_way_logs": {
367-
logFilename: "log-frontdoorwaflog.json",
368-
expectedFilename: "front-door-waf-log-expected.yaml",
369-
},
370407
"log_bad_time": {
371408
logFilename: "log-bad-time.json",
372409
expectedFilename: "log-bad-time-expected.yaml",

pkg/translator/azurelogs/testdata/expected/front-door-waf-log-expected.yaml

Lines changed: 0 additions & 47 deletions
This file was deleted.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"records":[
3+
{
4+
"time":"2025-04-24T15:35:06.0000000Z",
5+
"resourceId":"/SUBSCRIPTIONS/OPENTELEMETRY-AZURE-SUB/RESOURCEGROUPS/OPENTELEMETRY-FRONTDOOR/PROVIDERS/MICROSOFT.CDN/PROFILES/OPENTELEMETRY-FRONTDOOR-PROFILE",
6+
"category":"FrontDoorWebApplicationFirewallLog",
7+
"operationName":"Microsoft.Cdn/Profiles/WebApplicationFirewallLog/Write",
8+
"properties":{
9+
"clientIP":"2001:1c00:3280:6700:fbfa:bf04:1296:ebfc",
10+
"clientPort":"57660",
11+
"socketIP":"2001:1c00:3280:6700:fbfa:bf04:1296:ebfc",
12+
"requestUri":"http://opentelemetry-test-fmagg0exgdcfhefq.z01.azurefd.net:80/",
13+
"ruleName":"Rule1",
14+
"policy":"policy",
15+
"action":"Block",
16+
"host":"opentelemetry-test-fmagg0exgdcfhefq.z01.azurefd.net",
17+
"trackingReference":"20250424T153506Z-1756f49cc78nldhvhC1DUS3dhw000000080000000000d207",
18+
"policyMode":"prevention",
19+
"details":{
20+
"matches":[
21+
{
22+
"matchVariableName":"Method",
23+
"matchVariableValue":"GET"
24+
}
25+
],
26+
"msg":"",
27+
"data":""
28+
}
29+
}
30+
}
31+
]
32+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
resourceLogs:
2+
- resource:
3+
attributes:
4+
- key: cloud.provider
5+
value:
6+
stringValue: azure
7+
- key: cloud.resource_id
8+
value:
9+
stringValue: /SUBSCRIPTIONS/OPENTELEMETRY-AZURE-SUB/RESOURCEGROUPS/OPENTELEMETRY-FRONTDOOR/PROVIDERS/MICROSOFT.CDN/PROFILES/OPENTELEMETRY-FRONTDOOR-PROFILE
10+
- key: event.name
11+
value:
12+
stringValue: az.resource.log
13+
scopeLogs:
14+
- logRecords:
15+
- attributes:
16+
- key: client.port
17+
value:
18+
intValue: "57660"
19+
- key: url.original
20+
value:
21+
stringValue: http://opentelemetry-test-fmagg0exgdcfhefq.z01.azurefd.net:80/
22+
- key: url.port
23+
value:
24+
intValue: "80"
25+
- key: url.scheme
26+
value:
27+
stringValue: http
28+
- key: url.path
29+
value:
30+
stringValue: /
31+
- key: client.address
32+
value:
33+
stringValue: 2001:1c00:3280:6700:fbfa:bf04:1296:ebfc
34+
- key: source.address
35+
value:
36+
stringValue: 2001:1c00:3280:6700:fbfa:bf04:1296:ebfc
37+
- key: azure.ref
38+
value:
39+
stringValue: 20250424T153506Z-1756f49cc78nldhvhC1DUS3dhw000000080000000000d207
40+
- key: http.request.header.host
41+
value:
42+
stringValue: opentelemetry-test-fmagg0exgdcfhefq.z01.azurefd.net
43+
- key: azure.frontdoor.waf.policy.name
44+
value:
45+
stringValue: policy
46+
- key: azure.frontdoor.waf.policy.mode
47+
value:
48+
stringValue: prevention
49+
- key: azure.frontdoor.waf.rule.name
50+
value:
51+
stringValue: Rule1
52+
- key: azure.frontdoor.waf.action
53+
value:
54+
stringValue: Block
55+
- key: azure.category
56+
value:
57+
stringValue: FrontDoorWebApplicationFirewallLog
58+
- key: azure.operation.name
59+
value:
60+
stringValue: Microsoft.Cdn/Profiles/WebApplicationFirewallLog/Write
61+
body: {}
62+
spanId: ""
63+
timeUnixNano: "1745508906000000000"
64+
traceId: ""
65+
scope:
66+
name: otelcol/azureresourcelogs
67+
version: 1.2.3

0 commit comments

Comments
 (0)