Skip to content

Commit 55439b6

Browse files
authored
[Cloudflare Logpush] - Added support for Azure Blob Storage input in all data streams (elastic#15440)
Added support for Azure Blob Storage input in all data streams along with relevant system, policy tests and updated documentation.
1 parent ff17f81 commit 55439b6

File tree

134 files changed

+6704
-10
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

134 files changed

+6704
-10
lines changed

packages/cloudflare_logpush/_dev/build/docs/README.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44

55
The [Cloudflare Logpush](https://www.cloudflare.com/) integration allows you to monitor Access Request, Audit, CASB, Device Posture, DNS, DNS Firewall, Firewall Event, Gateway DNS, Gateway HTTP, Gateway Network, HTTP Request, Magic IDS, NEL Report, Network Analytics, Sinkhole HTTP, Spectrum Event, Network Session and Workers Trace Events logs. Cloudflare is a content delivery network and DDoS mitigation company. Cloudflare provides a network designed to make everything you connect to the Internet secure, private, fast, and reliable; secure your websites, APIs, and Internet applications; protect corporate networks, employees, and devices; and write and deploy code that runs on the network edge.
66

7-
The Cloudflare Logpush integration can be used in three different modes to collect data:
7+
The Cloudflare Logpush integration can be used in the following modes to collect data:
88
- HTTP Endpoint mode - Cloudflare pushes logs directly to an HTTP endpoint hosted by your Elastic Agent.
99
- AWS S3 polling mode - Cloudflare writes data to S3 and Elastic Agent polls the S3 bucket by listing its contents and reading new files.
1010
- AWS S3 SQS mode - Cloudflare writes data to S3, S3 pushes a new object notification to SQS, Elastic Agent receives the notification from SQS, and then reads the S3 object. Multiple Agents can be used in this mode.
11+
- Azure Blob Storage polling mode - Cloudflare writes data to Azure Blob Storage and Elastic Agent polls the Azure Blob Storage containers by listing its contents and reading new files.
12+
- Google Cloud Storage polling mode - Cloudflare writes data to Google Cloud Storage and Elastic Agent polls the GCS buckets by listing its contents and reading new files.
1113

1214
For example, you could use the data from this integration to know which websites have the highest traffic, which areas have the highest network traffic, or observe mitigation statistics.
1315

@@ -136,13 +138,25 @@ When configuring the integration to read from S3-Compatible Buckets such as Clou
136138
### Collect data from GCS Buckets
137139

138140
- Configure the [Data Forwarder](https://developers.cloudflare.com/logs/get-started/enable-destinations/google-cloud-storage/) to ingest data into a GCS bucket.
139-
- Configure the GCS bucket names and credentials along with the required configs under the "Collect Cloudflare Logpush logs via Google Cloud Storage" section.
141+
- Configure the GCS bucket names and credentials along with the required configurations under the "Collect Cloudflare Logpush logs via Google Cloud Storage" section.
140142
- Make sure the service account and authentication being used, has proper levels of access to the GCS bucket [Manage Service Account Keys](https://cloud.google.com/iam/docs/creating-managing-service-account-keys/)
141143

142144
**Note**:
143145
- The GCS input currently does not support fetching of buckets using bucket prefixes, so the bucket names have to be configured manually for each data stream.
144-
- The GCS input currently only accepts a service account JSON key or a service account JSON file for authentication.
145-
- The GCS input currently only supports json data.
146+
- The GCS input accepts a service account JSON key or a service account JSON file for authentication.
147+
- The GCS input supports JSON/NDJSON data.
148+
149+
### Collect data from Azure Blob Storage
150+
151+
- [Enable Microsoft Azure](https://developers.cloudflare.com/logs/logpush/logpush-job/enable-destinations/azure/) to ingest data into Azure Blob Storage containers.
152+
- Configure Azure Blob Storage container names and credentials along with the required configurations under the "Collect Cloudflare Logpush logs via Azure Blob Storage" section.
153+
- Make sure the storage account and authentication being used, has proper levels of access to the Azure Blob Storage Container. Please follow the documentation [here](https://learn.microsoft.com/en-us/azure/storage/blobs/authorize-data-operations-portal) for more details.
154+
- If you want to use RBAC for your account please follow the documentation [here](https://learn.microsoft.com/en-us/azure/storage/blobs/authorize-access-azure-active-directory).
155+
156+
**Note**:
157+
- The Azure Blob Storage input does not support fetching from containers using container prefixes, so the containers' names must be configured manually for each data stream.
158+
- The Azure Blob Storage input accepts a service account key (shared credentials key), service account URI (connection string) and OAuth2 credentials for authentication.
159+
- The Azure Blob Storage input only supports JSON/NDJSON data.
146160

147161
### Collect data from the Cloudflare HTTP Endpoint
148162

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
FROM node:current-bullseye-slim
2+
3+
# Install dependencies
4+
RUN apt-get update && apt-get install -y \
5+
curl \
6+
netcat \
7+
ca-certificates \
8+
lsb-release \
9+
&& rm -rf /var/lib/apt/lists/*
10+
# Install Azurite
11+
RUN npm install -g azurite
12+
13+
# Install Azure CLI
14+
RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash
15+
16+
# Copy emulator script
17+
COPY files/emulator.sh /emulator.sh
18+
RUN chmod +x /emulator.sh
19+
20+
ENTRYPOINT ["/bin/sh", "/emulator.sh"]

packages/cloudflare_logpush/_dev/deploy/docker/docker-compose.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,14 @@ services:
189189
- STREAM_WEBHOOK_PROBE=false
190190
- STREAM_ADDR=http://elastic-agent:9560/cloudflare_logpush/dns_firewall
191191
command: log --start-signal=SIGHUP --delay=5s /sample_logs/dns_firewall.log
192+
193+
azure-blob-storage-emulator:
194+
build: .
195+
volumes:
196+
- ./sample_logs:/sample_logs
197+
ports:
198+
- "10000/tcp"
199+
healthcheck:
200+
test: "curl --fail --silent --output /dev/null http://localhost:4443 || exit 1"
201+
interval: 10s
202+
timeout: 5s
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# Set environment variables for Azure cli
5+
export AZURE_STORAGE_ACCOUNT=devstoreaccount1
6+
export AZURE_STORAGE_KEY="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
7+
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=http;AccountName=$AZURE_STORAGE_ACCOUNT;AccountKey=$AZURE_STORAGE_KEY;BlobEndpoint=http://127.0.0.1:10000/$AZURE_STORAGE_ACCOUNT;"
8+
9+
# Start Azurite in background
10+
azurite-blob --blobHost 0.0.0.0 --blobPort 10000 --skipApiVersionCheck &
11+
AZURITE_PID=$!
12+
13+
# Wait until Azurite is ready
14+
while ! nc -z 127.0.0.1 10000; do sleep 0.5; done
15+
16+
# Create container
17+
az storage container create --name test-container
18+
19+
# Upload all files
20+
for f in /sample_logs/*; do
21+
if [ -f "$f" ]; then
22+
az storage blob upload --container-name test-container --file "$f" --name "$(basename "$f")"
23+
fi
24+
done
25+
26+
node -e "
27+
const http = require('http');
28+
const server = http.createServer((req, res) => { res.writeHead(200); res.end('OK'); });
29+
server.listen(4443, () => console.log('Healthcheck API available on port 4443'));
30+
" &
31+
32+
echo "All files uploaded. Healthcheck API started."
33+
34+
# Keep Azurite running
35+
wait $AZURITE_PID
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
{"BotDetectionIDs":[7,8,9],"BotScore":20,"BotScoreSrc":"Verified Bot","BotTags":["bing","api"],"CacheCacheStatus":"dynamic","CacheResponseBytes":983828,"CacheResponseStatus":200,"CacheTieredFill":false,"ClientASN":43766,"ClientCountry":"sa","ClientDeviceType":"desktop","ClientIP":"175.16.199.0","ClientIPClass":"noRecord","ClientMTLSAuthCertFingerprint":"Fingerprint","ClientMTLSAuthStatus":"unknown","ClientRequestBytes":5800,"ClientRequestHost":"xyz.example.com","ClientRequestMethod":"POST","ClientRequestPath":"/xyz/checkout","ClientRequestProtocol":"HTTP/1.1","ClientRequestReferer":"https://example.com/s/example/default?sourcerer=(default:(id:!n,selectedPatterns:!(example,%27logs-endpoint.*-example%27,%27logs-system.*-example%27,%27logs-windows.*-example%27)))&timerange=(global:(linkTo:!(),timerange:(from:%272022-05-16T06:26:36.340Z%27,fromStr:now-24h,kind:relative,to:%272022-05-17T06:26:36.340Z%27,toStr:now)),timeline:(linkTo:!(),timerange:(from:%272022-04-17T22:00:00.000Z%27,kind:absolute,to:%272022-04-18T21:59:59.999Z%27)))&timeline=(activeTab:notes,graphEventId:%27%27,id:%279844bdd4-4dd6-5b22-ab40-3cd46fce8d6b%27,isOpen:!t)","ClientRequestScheme":"https","ClientRequestSource":"edgeWorkerFetch","ClientRequestURI":"/s/example/api/telemetry/v2/clusters/_stats","ClientRequestUserAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36","ClientSrcPort":0,"ClientSSLCipher":"NONE","ClientSSLProtocol":"TLSv1.2","ClientTCPRTTMs":0,"ClientXRequestedWith":"Request With","Cookies":{"key":"value"},"EdgeCFConnectingO2O":false,"EdgeColoCode":"RUH","EdgeColoID":339,"EdgeEndTimestamp":"2022-05-25T13:25:32Z","EdgePathingOp":"wl","EdgePathingSrc":"macro","EdgePathingStatus":"nr","EdgeRateLimitAction":"unknown","EdgeRateLimitID":0,"EdgeRequestHost":"abc.example.com","EdgeResponseBodyBytes":980397,"EdgeResponseBytes":981308,"EdgeResponseCompressionRatio":0,"EdgeResponseContentType":"application/json","EdgeResponseStatus":200,"EdgeServerIP":"1.128.0.0","EdgeStartTimestamp":"2022-05-25T13:25:26Z","EdgeTimeToFirstByteMs":5333,"OriginDNSResponseTimeMs":3,"OriginIP":"67.43.156.0","OriginRequestHeaderSendDurationMs":0,"OriginResponseBytes":0,"OriginResponseDurationMs":5319,"OriginResponseHeaderReceiveDurationMs":5155,"OriginResponseHTTPExpires":"2022-05-27T13:25:26Z","OriginResponseHTTPLastModified":"2022-05-26T13:25:26Z","OriginResponseStatus":200,"OriginResponseTime":5232000000,"OriginSSLProtocol":"TLSv1.2","OriginTCPHandshakeDurationMs":24,"OriginTLSHandshakeDurationMs":53,"ParentRayID":"710e98d93d50357d","RayID":"710e98d9367f357d","SecurityLevel":"off","SmartRouteColoID":20,"UpperTierColoID":0,"SecurityAction":"unknown","WAFAttackScore":50,"WAFRCEAttackScore":1,"WAFSQLiAttackScore":99,"WAFXSSAttackScore":90,"WAFFlags":"0","WAFMatchedVar":"example","WAFProfile":"unknown","SecurityRuleID":"98d93d5","SecurityRuleDescription":"matchad variable message","WorkerCPUTime":0,"WorkerStatus":"unknown","WorkerSubrequest":true,"WorkerSubrequestCount":0,"ZoneID":393347122,"ZoneName":"example.com"}
2+
{"ClientASN":8075,"ClientCountry":"NL","ClientDeviceType":"desktop","ClientIP":"89.160.20.156","ClientIPClass":"noRecord","ClientRequestBytes":7495,"ClientRequestHost":"api.deals-referral.com","ClientRequestMethod":"GET","ClientRequestPath":"/referralapi/api/deals/find","ClientRequestProtocol":"HTTP/1.1","ClientRequestReferer":"https://www.main-site.com/user/dashboard","ClientRequestURI":"/referralapi/api/deals/find?pricingCaseId=68c15fccf03482a4cb20460b","ClientRequestUserAgent":"got (https://github.com/sindresorhus/got)","ClientSSLCipher":"AEAD-AES256-GCM-SHA384","ClientSSLProtocol":"TLSv1.3","ClientSrcPort":32462,"ClientXRequestedWith":"XMLHttpRequest","EdgeColoCode":"AMS","EdgeColoID":996,"EdgeEndTimestamp":"2025-09-17T08:37:18.000Z","EdgePathingOp":"wl","EdgePathingSrc":"undef","EdgePathingStatus":"nr","EdgeRateLimitAction":"log","EdgeRateLimitID":12345,"EdgeRequestHost":"api.deals-referral.com","EdgeResponseBytes":1063,"EdgeResponseCompressionRatio":1,"EdgeResponseContentType":"application/json; charset=utf-8","EdgeResponseStatus":200,"EdgeServerIP":"89.160.20.156","EdgeStartTimestamp":"2025-09-17T08:37:18.000Z","EdgeTimeToFirstByteMs":65,"FirewallMatchesActions":"skip","FirewallMatchesRuleIDs":"fddd53f90acd49a89aea84e1c665269c","FirewallMatchesSources":"firewallManaged","OriginDNSResponseTimeMs":2,"OriginIP":"172.16.10.100","OriginResponseBytes":980,"OriginResponseDurationMs":62,"OriginResponseHTTPExpires":"Wed, 17 Sep 2025 08:42:18 GMT","OriginResponseHTTPLastModified":"Wed, 17 Sep 2025 08:30:00 GMT","OriginResponseStatus":200,"OriginResponseTime":62543210,"OriginSSLProtocol":"TLSv1.3","ParentRayID":"980747e7ad8f0001","RayID":"980747e7ad8fbdf3","SecurityLevel":"high","WAFAction":"log","WAFFlags":"0","WAFMatchedVar":"ARGS:pricingCaseId","WAFProfile":"default","WAFRuleID":"942100","WAFRuleMessage":"SQL Injection Attack Detected","WorkerCPUTime":1601,"WorkerStatus":"ok","WorkerSubrequest":false,"WorkerSubrequestCount":1,"WorkerWallTimeUs":36953,"ZoneID":296364127}

packages/cloudflare_logpush/changelog.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
# newer versions go on top
2+
- version: "1.40.0"
3+
changes:
4+
- description: Added support for Azure Blob Storage input for all data streams.
5+
type: enhancement
6+
link: https://github.com/elastic/integrations/pull/15440
27
- version: "1.39.2"
38
changes:
49
- description: Do not convert timestamps in spectrum_event datastream that are 0, "0" or "".
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
inputs:
2+
- data_stream:
3+
namespace: ep
4+
meta:
5+
package:
6+
name: cloudflare_logpush
7+
name: test-abs-cloudflare_logpush
8+
streams:
9+
- account_name: devstoreaccount1
10+
auth.connection_string.uri: DefaultEndpointsProtocol=https;AccountName=dummystorageacct;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;EndpointSuffix=core.windows.net
11+
auth.oauth2:
12+
client_id: ${SECRET_0}
13+
client_secret: ${SECRET_1}
14+
tenant_id: 12345
15+
auth.shared_credentials.account_key: ${SECRET_2}
16+
containers:
17+
- name: test-container
18+
data_stream:
19+
dataset: cloudflare_logpush.access_request
20+
expand_event_list_from_field: records
21+
file_selectors:
22+
- regex: access-logs/
23+
max_workers: 3
24+
poll: true
25+
poll_interval: 15s
26+
processors:
27+
- decode_json_fields:
28+
fields:
29+
- message
30+
max_depth: 10
31+
overwrite_keys: true
32+
process_array: true
33+
target: ""
34+
publisher_pipeline.disable_host: true
35+
tags:
36+
- preserve_original_event
37+
- preserve_duplicate_custom_fields
38+
- forwarded
39+
timestamp_epoch: 10000000000
40+
type: azure-blob-storage
41+
use_output: default
42+
output_permissions:
43+
default:
44+
_elastic_agent_checks:
45+
cluster:
46+
- monitor
47+
_elastic_agent_monitoring:
48+
indices: []
49+
uuid-for-permissions-on-related-indices:
50+
indices:
51+
- names:
52+
- logs-cloudflare_logpush.access_request-ep
53+
privileges:
54+
- auto_configure
55+
- create_doc
56+
secret_references:
57+
- {}
58+
- {}
59+
- {}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
input: azure-blob-storage
2+
vars:
3+
account_name: devstoreaccount1
4+
oauth2: true
5+
client_id: devstoreaccount1
6+
tenant_id: 12345
7+
client_secret: Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==
8+
service_account_key: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
9+
service_account_uri: DefaultEndpointsProtocol=https;AccountName=dummystorageacct;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;EndpointSuffix=core.windows.net
10+
data_stream:
11+
vars:
12+
number_of_workers: 3
13+
poll: true
14+
poll_interval: 15s
15+
containers: |
16+
- name: test-container
17+
file_selectors: |
18+
- regex: access-logs/
19+
timestamp_epoch: 10000000000
20+
expand_event_list_from_field: records
21+
preserve_original_event: true
22+
preserve_duplicate_custom_fields: true
23+
processors: |
24+
- decode_json_fields:
25+
fields: ["message"]
26+
process_array: true
27+
max_depth: 10
28+
target: ""
29+
overwrite_keys: true
30+
tags:
31+
- forwarded
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
deployer: docker
2+
service: azure-blob-storage-emulator
3+
input: azure-blob-storage
4+
vars:
5+
account_name: devstoreaccount1
6+
service_account_key: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
7+
storage_url: "http://{{Hostname}}:{{Port}}/devstoreaccount1/"
8+
data_stream:
9+
vars:
10+
number_of_workers: 1
11+
poll: true
12+
poll_interval: 15s
13+
containers: |
14+
- name: test-container
15+
file_selectors: |
16+
- regex: "access_request"
17+
assert:
18+
hit_count: 1
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{{#if account_name}}
2+
account_name: {{account_name}}
3+
{{/if}}
4+
{{#if oauth2}}
5+
auth.oauth2:
6+
client_id: {{client_id}}
7+
client_secret: {{client_secret}}
8+
tenant_id: {{tenant_id}}
9+
{{/if}}
10+
{{#if service_account_key}}
11+
auth.shared_credentials.account_key: {{service_account_key}}
12+
{{/if}}
13+
{{#if service_account_uri}}
14+
auth.connection_string.uri: {{service_account_uri}}
15+
{{/if}}
16+
{{#if storage_url}}
17+
storage_url: {{storage_url}}
18+
{{/if}}
19+
{{#if number_of_workers}}
20+
max_workers: {{number_of_workers}}
21+
{{/if}}
22+
{{#if poll}}
23+
poll: {{poll}}
24+
{{/if}}
25+
{{#if poll_interval}}
26+
poll_interval: {{poll_interval}}
27+
{{/if}}
28+
29+
{{#if containers}}
30+
containers:
31+
{{containers}}
32+
{{/if}}
33+
{{#if file_selectors}}
34+
file_selectors:
35+
{{file_selectors}}
36+
{{/if}}
37+
{{#if timestamp_epoch}}
38+
timestamp_epoch: {{timestamp_epoch}}
39+
{{/if}}
40+
{{#if expand_event_list_from_field}}
41+
expand_event_list_from_field: {{expand_event_list_from_field}}
42+
{{/if}}
43+
44+
tags:
45+
{{#if preserve_original_event}}
46+
- preserve_original_event
47+
{{/if}}
48+
{{#if preserve_duplicate_custom_fields}}
49+
- preserve_duplicate_custom_fields
50+
{{/if}}
51+
{{#each tags as |tag|}}
52+
- {{tag}}
53+
{{/each}}
54+
{{#contains "forwarded" tags}}
55+
publisher_pipeline.disable_host: true
56+
{{/contains}}
57+
{{#if processors}}
58+
processors:
59+
{{processors}}
60+
{{/if}}

0 commit comments

Comments
 (0)