Skip to content

Commit 9e4eacb

Browse files
authored
Merge pull request #1 from splunk/event-hubs
Merge Event Hub functions
2 parents fbc6b9d + d6f772c commit 9e4eacb

Some content is hidden

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

61 files changed

+27206
-60
lines changed

Diff for: .gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,7 @@ out
9191
bin
9292
obj
9393
appsettings.json
94-
local.settings.json
94+
local.settings.json
95+
96+
# Workstation
97+
.DS_Store

Diff for: .vscode/settings.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
2-
"azureFunctions.deploySubpath": "graph",
32
"azureFunctions.postDeployTask": "npm install",
43
"azureFunctions.projectLanguage": "JavaScript",
54
"azureFunctions.projectRuntime": "~3",
65
"debug.internalConsoleOptions": "neverOpen",
7-
"azureFunctions.preDeployTask": "npm prune"
6+
"azureFunctions.preDeployTask": "npm prune",
7+
"azureFunctions.deploySubpath": "event-hubs-hec",
8+
"azureFunctions.projectSubpath": "event-hubs-hec"
89
}

Diff for: .vscode/tasks.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
{
55
"type": "func",
66
"command": "host start",
7-
"problemMatcher": "$func-watch",
7+
"problemMatcher": "$func-node-watch",
88
"isBackground": true,
99
"dependsOn": "npm install",
1010
"options": {
11-
"cwd": "${workspaceFolder}/graph"
11+
"cwd": "${workspaceFolder}/event-hubs-hec"
1212
}
1313
},
1414
{
1515
"type": "shell",
1616
"label": "npm install",
1717
"command": "npm install",
1818
"options": {
19-
"cwd": "${workspaceFolder}/graph"
19+
"cwd": "${workspaceFolder}/event-hubs-hec"
2020
}
2121
},
2222
{
@@ -25,7 +25,7 @@
2525
"command": "npm prune --production",
2626
"problemMatcher": [],
2727
"options": {
28-
"cwd": "${workspaceFolder}/graph"
28+
"cwd": "${workspaceFolder}/event-hubs-hec"
2929
}
3030
}
3131
]

Diff for: README.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,23 @@ Each available set of functions in this repository is contained within its own f
1111
| Functions | Location | Description |
1212
| --------- | -------- | ----------- |
1313
| Microsoft Teams | [graph](https://github.com/splunk/azure-functions-splunk/tree/master/graph) | Collects [Microsoft Teams call records]( https://docs.microsoft.com/en-us/graph/api/resources/callrecords-callrecord). This data can be used with the [Microsoft 365 App for Splunk]( https://splunkbase.splunk.com/app/3786/) and/or the [RWI – Executive Dashboard]( https://splunkbase.splunk.com/app/4952/) |
14-
14+
| Azure Event Hubs | [event-hubs-hec](https://github.com/splunk/azure-functions-splunk/tree/master/event-hubs) | These Azure Functions are triggered by events arriving on an Azure Event Hub. The functions then process the events and send the event to a listening Splunk HTTP Event Collector |
15+
16+
## Setting a Project Subpath
17+
[Multiple Azure Function projects](https://github.com/Microsoft/vscode-azurefunctions/wiki/Multiple-function-projects) exist in this repository. In order to debug a specific function project, set the `azureFunctions.deploySubpath` and `azureFunctions.projectSubpath` parameters in `settings.json` to the appropriate path.
18+
19+
For example, to run and debug the `Graph` functions use the following `settings.json`
20+
```
21+
{
22+
"azureFunctions.postDeployTask": "npm install",
23+
"azureFunctions.projectLanguage": "JavaScript",
24+
"azureFunctions.projectRuntime": "~3",
25+
"debug.internalConsoleOptions": "neverOpen",
26+
"azureFunctions.preDeployTask": "npm prune",
27+
"azureFunctions.deploySubpath": "graph",
28+
"azureFunctions.projectSubpath": "graph"
29+
}
30+
```
1531

1632
## Support
1733

Diff for: event-hubs-hec/.funcignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
*.js.map
2+
*.ts
3+
.git*
4+
.vscode
5+
local.settings.json
6+
test
7+
tsconfig.json

Diff for: event-hubs-hec/.gitignore

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
lerna-debug.log*
8+
9+
# Diagnostic reports (https://nodejs.org/api/report.html)
10+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11+
12+
# Runtime data
13+
pids
14+
*.pid
15+
*.seed
16+
*.pid.lock
17+
18+
# Directory for instrumented libs generated by jscoverage/JSCover
19+
lib-cov
20+
21+
# Coverage directory used by tools like istanbul
22+
coverage
23+
24+
# nyc test coverage
25+
.nyc_output
26+
27+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
28+
.grunt
29+
30+
# Bower dependency directory (https://bower.io/)
31+
bower_components
32+
33+
# node-waf configuration
34+
.lock-wscript
35+
36+
# Compiled binary addons (https://nodejs.org/api/addons.html)
37+
build/Release
38+
39+
# Dependency directories
40+
node_modules/
41+
jspm_packages/
42+
43+
# TypeScript v1 declaration files
44+
typings/
45+
46+
# Optional npm cache directory
47+
.npm
48+
49+
# Optional eslint cache
50+
.eslintcache
51+
52+
# Optional REPL history
53+
.node_repl_history
54+
55+
# Output of 'npm pack'
56+
*.tgz
57+
58+
# Yarn Integrity file
59+
.yarn-integrity
60+
61+
# dotenv environment variables file
62+
.env
63+
.env.test
64+
65+
# parcel-bundler cache (https://parceljs.org/)
66+
.cache
67+
68+
# next.js build output
69+
.next
70+
71+
# nuxt.js build output
72+
.nuxt
73+
74+
# vuepress build output
75+
.vuepress/dist
76+
77+
# Serverless directories
78+
.serverless/
79+
80+
# FuseBox cache
81+
.fusebox/
82+
83+
# DynamoDB Local files
84+
.dynamodb/
85+
86+
# TypeScript output
87+
dist
88+
out
89+
90+
# Azure Functions artifacts
91+
bin
92+
obj
93+
appsettings.json
94+
local.settings.json

Diff for: event-hubs-hec/README.md

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Azure Functions for Sending Event Hub data to a Splunk HTTP Event Collector
2+
Events arriving on an Azure Event Hub can trigger serverless Azure Functions. Azure Functions can further process the raw events in near real-time.
3+
4+
<a href="https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fsplunk%2Fazure-functions-splunk%2Fevent-hubs%2Fevent-hubs-hec%2Fdeploy%2FazureDeploy.json/createUIDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2Fsplunk%2Fazure-functions-splunk%2Fevent-hubs%2Fevent-hubs-hec%2Fdeploy%2FazureDeploy.portal.json" target="_blank">
5+
<img src="https://aka.ms/deploytoazurebutton"/>
6+
</a>
7+
8+
This repository contains a collection of Azure Functions for:
9+
* Processing events as they arrive on an Event Hub
10+
* Separating batched events (events in a `records[]` array) into individual events
11+
* Formatting events in the `event` format for a Splunk HTTP Event Collector
12+
* Sending event data to Splunk via [HTTP Event Collector](https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector)
13+
* Writing event data to a Storage Blob if data cannot successfully be sent to Splunk
14+
* The [Splunk Add-on for Microsoft Cloud Services](https://splunkbase.splunk.com/app/3110/) can be utilized to retrieve Storage Blob data
15+
16+
## Getting Started
17+
18+
### 1. Create an HTTP Event Collector token in your Spunk Environment
19+
An HTTP Event Collector receives data pushed from the Azure Functions. Refer to the Splunk documentation for [setting up an HTTP Event Collector input](https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector) in your Splunk Enterprise or Splunk Cloud environment.
20+
21+
### 2. Create an Event Hub Namespace
22+
An Event Hub Namespace will contain one or more Event Hubs. Refer to the Microsoft documentation for [Event Hub Namespace setup instructions](https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-create).
23+
24+
### 3. Send data to an Event Hub
25+
Microsoft Azure uses [diagnostics settings](https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/diagnostic-settings) to define data export and destination rules. Each resource to be monitored must have a diagnostic setting. Diagnostic settings can be defined using the Azure portal, PowerShell, [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/monitor/diagnostic-settings?view=azure-cli-latest), [Resource Manager templates](https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/resource-manager-diagnostic-settings), REST API, or an Azure Policy.
26+
27+
* [Sending Azure Activity log data to an Event Hub using the Azure Portal walkthrough](docs/activity_log_diagnostic_settings.md)
28+
* [Sending Azure Diagnostic logs and metrics to an Event Hub](https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/diagnostic-settings)
29+
* [Sending Azure Active Directory logs to an Event Hub](docs/azure_ad_diagnostic_settings.md)
30+
* Sending Azure Virtual Machine data to an Event Hub
31+
* [Windows VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/diagnostics-windows)
32+
* [Linux VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/diagnostics-linux)
33+
34+
35+
### 4. Deploy the functions to Azure
36+
37+
Use the "Deploy to Azure" button above to deploy the Azure Functions from this repo to your Azure account. During setup, you will be prompted for the following information:
38+
39+
* Event Hub Namespace
40+
* Event Hub consumer group for each hub monitored
41+
* Splunk sourcetype or sourcetype base for each hub monitored
42+
* Note: see section below about sourcetypes
43+
* Splunk [HTTP Event Collector](https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector) Endpoint
44+
* Splunk [HTTP Event Collector](https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector) Token
45+
46+
## Splunk Sourcetypes
47+
### Azure Active Directory Sourcetypes
48+
Functions that collect Azure Active Directory data use a sourcetype base. The category of the Azure Active Directory event is appended to the sourcetype base to construct the full sourcetype.
49+
50+
**Example**
51+
52+
The default sourcetype base for Azure Active Directory Sign-in and Audit events is `azure:aad`
53+
54+
A sign-in event with a category of `SignInLogs` will have a sourcetype of `azure:aad:signinlogs`
55+
56+
An audit event with a category of `AuditLogs` will have a sourcetype of `azure:aad:auditlogs`
57+
58+
### Diagnostic Logs
59+
Functions that collect diagnostic log data attempt to construct a sourcetype based on the `resourceId` of the event. The logic for this sourcetype construction can be found in the `getSourceType` function in the [./helpers/splunk.js file](helpers/splunk.js). The following steps are used to construct the sourcetype:
60+
61+
* A regular expression is used to extract two groups after the text `/PROVIDERS`
62+
* Example `/PROVIDERS/`**`MICROSOFT.RESOURCES/DEPLOYMENTS/`**
63+
* Periods (`.`) and forward slashes (`/`) are replaced with colons (`:`)
64+
* The event category is appended
65+
66+
**Example**
67+
68+
An event with a `resourceId` of `/SUBSCRIPTIONS/subscription ID/RESOURCEGROUPS/group/PROVIDERS/MICROSOFT.RESOURCES/DEPLOYMENTS/FAILURE-ANOMALIES-ALERT-RULE-DEPLOYMENT-12345678` will have a sourcetype of `azure:resources:deployments:administrative`
69+
70+
If a sourcetype cannot be constructed from the event, the specified default sourcetype entered at setup will be used.
71+
72+
73+
## Securing Azure Function settings
74+
Microsoft stores the above values as [application settings](https://docs.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings#settings). These settings are stored encrypted, but you may opt to transfer one or more of these settings to a Key Vault. Refer to the following documentation for details on this procedure:
75+
76+
* [Use Key Vault references for App Service and Azure Functions](https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references)
77+
78+
79+
## Support
80+
This software is released as-is. Splunk provides no warranty and no support on this software. If you have any issues with the software, please file an issue on the repository.

Diff for: event-hubs-hec/aad-logs/function.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"bindings": [
3+
{
4+
"type": "eventHubTrigger",
5+
"name": "eventHubMessages",
6+
"direction": "in",
7+
"eventHubName": "%AAD_LOG_HUB_NAME%",
8+
"connection": "EVENTHUB_CONNECTION_STRING",
9+
"cardinality": "many",
10+
"consumerGroup": "%AAD_LOG_CONSUMER_GROUP%",
11+
"dataType": "string"
12+
},
13+
{
14+
"name": "outputBlob",
15+
"type": "blob",
16+
"path": "undeliverable-events/%AAD_LOG_SOURCETYPE%-{rand-guid}",
17+
"connection": "BLOB_CONNECTION_STRING",
18+
"direction": "out"
19+
}
20+
]
21+
}

Diff for: event-hubs-hec/aad-logs/index.js

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Copyright 2020 Splunk Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
const splunk = require('../helpers/splunk');
17+
module.exports = async function (context, eventHubMessages) {
18+
19+
for (const event of eventHubMessages) {
20+
await splunk
21+
.sendToHEC(event, process.env["AAD_LOG_SOURCETYPE"])
22+
.catch(err => {
23+
context.log.error(`Error posting to Splunk HTTP Event Collector: ${err}`);
24+
25+
// If the event was not successfully sent to Splunk, drop the event in a storage blob
26+
context.bindings.outputBlob = event;
27+
})
28+
}
29+
context.done();
30+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"bindings": [
3+
{
4+
"type": "eventHubTrigger",
5+
"name": "eventHubMessages",
6+
"direction": "in",
7+
"eventHubName": "%AAD_NON_INTERACTIVE_SIGNIN_LOG_HUB_NAME%",
8+
"connection": "EVENTHUB_CONNECTION_STRING",
9+
"cardinality": "many",
10+
"consumerGroup": "%AAD_NON_INTERACTIVE_SIGNIN_LOG_CONSUMER_GROUP%",
11+
"dataType": "string"
12+
},
13+
{
14+
"name": "outputBlob",
15+
"type": "blob",
16+
"path": "undeliverable-events/%AAD_NON_INTERACTIVE_SIGNIN_LOG_SOURCETYPE%-{rand-guid}",
17+
"connection": "BLOB_CONNECTION_STRING",
18+
"direction": "out"
19+
}
20+
]
21+
}
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Copyright 2020 Splunk Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
const splunk = require('../helpers/splunk');
17+
module.exports = async function (context, eventHubMessages) {
18+
19+
for (const event of eventHubMessages) {
20+
await splunk
21+
.sendToHEC(event, process.env["AAD_NON_INTERACTIVE_SIGNIN_LOG_SOURCETYPE"])
22+
.catch(err => {
23+
context.log.error(`Error posting to Splunk HTTP Event Collector: ${err}`);
24+
25+
// If the event was not successfully sent to Splunk, drop the event in a storage blob
26+
context.bindings.outputBlob = event;
27+
})
28+
}
29+
context.done();
30+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"bindings": [
3+
{
4+
"type": "eventHubTrigger",
5+
"name": "eventHubMessages",
6+
"direction": "in",
7+
"eventHubName": "%AAD_SERVICE_PRINCIPAL_SIGNIN_LOG_HUB_NAME%",
8+
"connection": "EVENTHUB_CONNECTION_STRING",
9+
"cardinality": "many",
10+
"consumerGroup": "%AAD_SERVICE_PRINCIPAL_SIGNIN_LOG_CONSUMER_GROUP%",
11+
"dataType": "string"
12+
},
13+
{
14+
"name": "outputBlob",
15+
"type": "blob",
16+
"path": "undeliverable-events/%AAD_SERVICE_PRINCIPAL_SIGNIN_LOG_SOURCETYPE%-{rand-guid}",
17+
"connection": "BLOB_CONNECTION_STRING",
18+
"direction": "out"
19+
}
20+
]
21+
}

0 commit comments

Comments
 (0)