Skip to content

Commit

Permalink
Merge pull request #10379 from skeerthivasan/playbook-push
Browse files Browse the repository at this point in the history
Added Playbooks and Analytic Rules for Pure Storage Solutions
  • Loading branch information
v-prasadboke committed May 7, 2024
2 parents 419c661 + 5730ad4 commit cdcea0d
Show file tree
Hide file tree
Showing 10 changed files with 2,464 additions and 8 deletions.
44 changes: 44 additions & 0 deletions Solutions/Pure Storage/Analytic Rules/PureControllerFailed.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
id: c317b007-84e7-4449-93f4-4444f6638fd0
name: Pure Controller Failed
version: 1.0.0
kind: NRT
description: Detect controller failure and take appropriate response action.
severity: High
tactics:
- Execution
relevantTechniques:
- T0871
query: |-
Syslog
| where SyslogMessage has "purity.alert"
| extend Message = replace_regex(SyslogMessage, "#012", "\n")
| extend ParsedLog = extract_all(@"((?P<process>.*?)\[(?P<processid>.*?)\]:\s(?P<object>.*)\[(?P<responsecode>\w+)\][\s\S]*Severity:\s*(?P<severity>\S+)\s*(Tag:\s*(?P<reason>\S+))?\s*UTC([\s\S]*)Array Name:\s*(?P<objectname>\S+)\s*Domain:\s*(?P<domainorigin>\S+)\s*(?P<part2log>[\s\S]*))", dynamic(['process','processid','object','objectname','responsecode','severity','reason','domainorigin','part2log']), Message)
| mv-expand ParsedLog
| extend ResidueLog = tostring(ParsedLog[8])
| extend Rlog = extract_all(@"(((Suggested Action:\s*(?P<action>[\s\S]*)\s*Knowledge Base Article:\s*(?P<url>.*))|(Knowledge Base Article:\s*(?P<url>.*)\s*Suggested Action:\s*(?P<action>.*)\s*)|(Suggested Action:\s*(?P<action>[\s\S]*)))(([\s\S]*)Purity Version:\s*(?P<pversion>.*))?\s*([\s\S]*)Variables: \(below\)\s*(?P<subject>[\s\S]*))", dynamic(['action','url','pversion','subject']),ResidueLog)
| mv-expand Rlog
| extend PureLogType = ParsedLog[0], PureProcessID = ParsedLog[1], PureObject = ParsedLog[2], PureCode = ParsedLog[4], PureSeverity = ParsedLog[5], PureReason = ParsedLog[6], PureObjectName = ParsedLog[3], PureDomainOrigin = ParsedLog[7], PureAction = Rlog[0], PureUrl = Rlog[1], PureVersion = Rlog[2], PureMessage = Rlog[3]
| project-away ResidueLog, Rlog, ParsedLog
| where PureObject matches regex @"(Controllers ct[0-9] have failed)"
suppressionDuration: 5h
suppressionEnabled: false
eventGroupingSettings:
aggregationKind: SingleAlert
alertDetailsOverride:
alertDynamicProperties: []
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: HostIP
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
groupByEntities: []
groupByAlertDetails: []
groupByCustomDetails: []

53 changes: 53 additions & 0 deletions Solutions/Pure Storage/Analytic Rules/PureFailedLogin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
id: ed32b115-5001-43a7-a2bb-f53026db4d97
name: Pure Failed Login
version: 1.0.0
kind: NRT
description: Detect failed login attacks and delete user
severity: High
tactics:
- CredentialAccess
relevantTechniques:
- T1212
query: |-
Syslog
| where SyslogMessage has "purity.alert" and SyslogMessage has "invalid username or password"
| extend Message = SyslogMessage
| extend ParsedLog = extract_all(@"((?P<process>.*?)\[(?P<processid>.*?)\][\s\S]*?Array name:\s*'(?P<arrayname>\S+)'[\s\S]*?Controller:\s*'?(?P<controller>[^']+)'?[\s\S]*Interface:\s*'(?P<interface>\S+)'.*?User:\s'(?P<login>.*?)'\sLocation: '(?P<location>[^']+)'\sSublocation: '(?P<sublocation>[^']+)\s*(?P<part2log>[\s\S]*))", dynamic(['process', 'processid', 'arrayname', 'controller', 'interface','login', 'location', 'sublocation', 'part2log']), Message)
| mv-expand ParsedLog
| extend ResidueLog = tostring(ParsedLog[8])
| extend Rlog = extract_all(@"[\s\S]*Action:\s'(?P<action>[^']+)'[\s\S]*Method:\s'(?P<method>[^']+)'[\s\S]*Result:\s(?P<result>[^']+)[\s\S]*Description:\s'(?P<description>[^']*)'", dynamic(['action', 'method', 'result', 'description']), ResidueLog)
| mv-expand Rlog
| extend PureLogType = ParsedLog[0], PureProcessID = ParsedLog[1], PureArrayName = ParsedLog[2], PureController = ParsedLog[3], PureInterface = ParsedLog[4], PureLogin = ParsedLog [5], PureLocation = ParsedLog [6], PureSublocation = ParsedLog [7], PureAction = Rlog [0], PureMethod = Rlog [1], PureResult = Rlog [2], PureDescription = Rlog [3]
| project-away ResidueLog, Rlog, ParsedLog
| summarize count() by tostring(PureLogin), tostring(PureArrayName), HostIP
| where count_ >= 10
suppressionDuration: 5h
suppressionEnabled: false
eventGroupingSettings:
aggregationKind: SingleAlert
alertDetailsOverride:
alertDynamicProperties: []
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: HostIP
- entityType: Account
fieldMappings:
- identifier: Name
columnName: PureLogin
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: PureArrayName
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
groupByEntities: []
groupByAlertDetails: []
groupByCustomDetails: []

9 changes: 9 additions & 0 deletions Solutions/Pure Storage/Data/Solution_PureStorage.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
"Logo": "<img src=\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Logos/purestorage_logo.svg\" width=\"75px\" height=\"75px\">",
"Description": "Solution for Microsoft Sentinel to ingest logs from PureStorage arrays",
"Parsers": ["Parsers/PureStorageParser.yaml"],
"Analytic Rules": [
"Analytic Rules/PureFailedLogin.yaml",
"Analytic Rules/PureControllerFailed.yaml"
],
"Playbooks": [
"Playbooks/Pure-Storage-User-Delete/azuredeploy.json",
"Playbooks/Pure-Storage-Volumes-Snapshot/azuredeploy.json",
"Playbooks/Pure-Storage-Protection-Groups-Snapshot/azuredeploy.json"
],
"BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\Pure Storage",
"Version": "3.0.1",
"Metadata": "SolutionMetadata.json",
Expand Down
Binary file modified Solutions/Pure Storage/Package/3.0.1.zip
Binary file not shown.
89 changes: 87 additions & 2 deletions Solutions/Pure Storage/Package/createUiDefinition.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"config": {
"isWizard": false,
"basics": {
"description": "<img src=\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Logos/purestorage_logo.svg\" width=\"75px\" height=\"75px\">\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Pure%20Storage/ReleaseNotes.md)\n\n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nSolution for Microsoft Sentinel to ingest logs from PureStorage arrays\n\n**Parsers:** 1\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)",
"description": "<img src=\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Logos/purestorage_logo.svg\" width=\"75px\" height=\"75px\">\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Pure%20Storage/ReleaseNotes.md)\n\n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nSolution for Microsoft Sentinel to ingest logs from PureStorage arrays\n\n**Parsers:** 1, **Analytic Rules:** 2, **Playbooks:** 3\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)",
"subscription": {
"resourceProviders": [
"Microsoft.OperationsManagement/solutions",
Expand Down Expand Up @@ -50,7 +50,92 @@
"visible": true
}
],
"steps": [],
"steps": [
{
"name": "analytics",
"label": "Analytics",
"subLabel": {
"preValidation": "Configure the analytics",
"postValidation": "Done"
},
"bladeTitle": "Analytics",
"elements": [
{
"name": "analytics-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This solution installs the following analytic rule templates. After installing the solution, create and enable analytic rules in Manage solution view."
}
},
{
"name": "analytics-link",
"type": "Microsoft.Common.TextBlock",
"options": {
"link": {
"label": "Learn more",
"uri": "https://docs.microsoft.com/azure/sentinel/tutorial-detect-threats-custom?WT.mc_id=Portal-Microsoft_Azure_CreateUIDef"
}
}
},
{
"name": "analytic1",
"type": "Microsoft.Common.Section",
"label": "Pure Failed Login",
"elements": [
{
"name": "analytic1-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Detect failed login attacks and delete user"
}
}
]
},
{
"name": "analytic2",
"type": "Microsoft.Common.Section",
"label": "Pure Controller Failed",
"elements": [
{
"name": "analytic2-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "Detect controller failure and take appropriate response action."
}
}
]
}
]
},
{
"name": "playbooks",
"label": "Playbooks",
"subLabel": {
"preValidation": "Configure the playbooks",
"postValidation": "Done"
},
"bladeTitle": "Playbooks",
"elements": [
{
"name": "playbooks-text",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This solution installs the Playbook templates to help implement your Security Orchestration, Automation and Response (SOAR) operations. After installing the solution, these will be deployed under Playbook Templates in the Automation blade in Microsoft Sentinel. They can be configured and managed from the Manage solution view in Content Hub."
}
},
{
"name": "playbooks-link",
"type": "Microsoft.Common.TextBlock",
"options": {
"link": {
"label": "Learn more",
"uri": "https://docs.microsoft.com/azure/sentinel/tutorial-respond-threats-playbook?WT.mc_id=Portal-Microsoft_Azure_CreateUIDef"
}
}
}
]
}
],
"outputs": {
"workspace-location": "[first(map(filter(basics('getLAWorkspace').value, (filter) => and(contains(toLower(filter.id), toLower(resourceGroup().name)),equals(filter.name,basics('workspace')))), (item) => item.location))]",
"location": "[location()]",
Expand Down

0 comments on commit cdcea0d

Please sign in to comment.