Merge branch 'master' into machiliv/AnalyticalRulesValidationsIssueFixes
This commit is contained in:
Коммит
133f58a909
|
@ -1,80 +1 @@
|
|||
# Each pull request that updates ASimDns, ASimNetworkSession, or ASimWebSession parsers triggers the script.
|
||||
# The script generates deployable ARM templates based on ASim parsers YAML files and pushes them to the pull request branch.
|
||||
name: Convert Kql function yaml to ARM template
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize, labeled]
|
||||
paths:
|
||||
- 'Parsers/ASimDns/Parsers/**'
|
||||
- 'Parsers/ASimNetworkSession/Parsers/**'
|
||||
- 'Parsers/ASimWebSession/Parsers/**'
|
||||
- 'Parsers/ASimProcessEvent/Parsers/**'
|
||||
jobs:
|
||||
kqlFuncYaml2Arm:
|
||||
# The workflow should not run on forked repositories for security reasons
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout pull request branch
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
|
||||
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
|
||||
- name: Install python
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: '3.x'
|
||||
architecture: 'x64'
|
||||
- name: Install yamale package
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
yamale
|
||||
- name: Setup git config
|
||||
run: |
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git config --local user.email "<>"
|
||||
- name: Merge master into pull request branch
|
||||
run: |
|
||||
git merge origin/master
|
||||
Conflicts=$(git ls-files -u | wc -l)
|
||||
if [ "$Conflicts" -gt 0 ] ; then
|
||||
echo "There is a merge conflict. Aborting"
|
||||
git merge --abort
|
||||
exit 1
|
||||
fi
|
||||
- name: Run kqlFuncYaml2Arm script
|
||||
run: |
|
||||
.script/kqlFuncYaml2Arm.ps1
|
||||
shell: pwsh
|
||||
- name: Commit changes
|
||||
run: |
|
||||
# Stage the files and commit
|
||||
git add Parsers/*
|
||||
if git diff --staged --quiet; then
|
||||
echo "armTemplatesChanged=false" >> $GITHUB_ENV
|
||||
echo "Arm templates didn't changed, no changes to commit"
|
||||
else
|
||||
echo "armTemplatesChanged=true" >> $GITHUB_ENV
|
||||
git commit -m '[ASIM Parsers] Generate deployable ARM templates from KQL function YAML files.'
|
||||
echo "Arm templates were changed. Changes were committed"
|
||||
fi
|
||||
- name: Push changes
|
||||
uses: ad-m/github-push-action@master
|
||||
if: ${{ env.armTemplatesChanged == 'true' }}
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
branch: ${{ github.head_ref }}
|
||||
- name: Add comment
|
||||
uses: mshick/add-pr-comment@v1
|
||||
if: ${{ env.armTemplatesChanged == 'true' }}
|
||||
with:
|
||||
message: |
|
||||
ASIM parsers have been changed. ARM templates were regenerated from the updated KQL function YAML files.
|
||||
To find the new ARM templates, pull your branch.
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repo-token-user-login: 'github-actions[bot]' # The user.login for temporary GitHub tokens
|
||||
allow-repeats: false # This is the default
|
||||
# This workflow is disabled, please use convertKqlFunctionYamlToArmTemplate.yaml instead.
|
|
@ -0,0 +1,80 @@
|
|||
# Each pull request that updates ASimDns, ASimNetworkSession, or ASimWebSession parsers triggers the script.
|
||||
# The script generates deployable ARM templates based on ASim parsers YAML files and pushes them to the pull request branch.
|
||||
name: Convert Kql function yaml to ARM template
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize, labeled]
|
||||
paths:
|
||||
- 'Parsers/ASimDns/Parsers/**'
|
||||
- 'Parsers/ASimNetworkSession/Parsers/**'
|
||||
- 'Parsers/ASimWebSession/Parsers/**'
|
||||
- 'Parsers/ASimProcessEvent/Parsers/**'
|
||||
jobs:
|
||||
kqlFuncYaml2Arm:
|
||||
# The workflow should not run on forked repositories for security reasons
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout pull request branch
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
|
||||
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
|
||||
- name: Install python
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: '3.x'
|
||||
architecture: 'x64'
|
||||
- name: Install yamale package
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
yamale
|
||||
- name: Setup git config
|
||||
run: |
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git config --local user.email "<>"
|
||||
- name: Merge master into pull request branch
|
||||
run: |
|
||||
git merge origin/master
|
||||
Conflicts=$(git ls-files -u | wc -l)
|
||||
if [ "$Conflicts" -gt 0 ] ; then
|
||||
echo "There is a merge conflict. Aborting"
|
||||
git merge --abort
|
||||
exit 1
|
||||
fi
|
||||
- name: Run kqlFuncYaml2Arm script
|
||||
run: |
|
||||
.script/kqlFuncYaml2Arm.ps1
|
||||
shell: pwsh
|
||||
- name: Commit changes
|
||||
run: |
|
||||
# Stage the files and commit
|
||||
git add Parsers/*
|
||||
if git diff --staged --quiet; then
|
||||
echo "armTemplatesChanged=false" >> $GITHUB_ENV
|
||||
echo "Arm templates didn't changed, no changes to commit"
|
||||
else
|
||||
echo "armTemplatesChanged=true" >> $GITHUB_ENV
|
||||
git commit -m '[ASIM Parsers] Generate deployable ARM templates from KQL function YAML files.'
|
||||
echo "Arm templates were changed. Changes were committed"
|
||||
fi
|
||||
- name: Push changes
|
||||
uses: ad-m/github-push-action@master
|
||||
if: ${{ env.armTemplatesChanged == 'true' }}
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
branch: ${{ github.head_ref }}
|
||||
- name: Add comment
|
||||
uses: mshick/add-pr-comment@v1
|
||||
if: ${{ env.armTemplatesChanged == 'true' }}
|
||||
with:
|
||||
message: |
|
||||
ASIM parsers have been changed. ARM templates were regenerated from the updated KQL function YAML files.
|
||||
To find the new ARM templates, pull your branch.
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repo-token-user-login: 'github-actions[bot]' # The user.login for temporary GitHub tokens
|
||||
allow-repeats: false # This is the default
|
|
@ -0,0 +1,58 @@
|
|||
name: Run ASIM testers on "eco-connector-test" workspace
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize, labeled]
|
||||
paths:
|
||||
- 'Parsers/ASimDns/Parsers/**'
|
||||
- 'Parsers/ASimNetworkSession/Parsers/**'
|
||||
- 'Parsers/ASimWebSession/Parsers/**'
|
||||
- 'Parsers/ASimProcessEvent/Parsers/**'
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
runAsimTesters:
|
||||
# The workflow should not run on forked repositories for security reasons
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout pull request branch
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
|
||||
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
|
||||
- name: Login to Azure Public Cloud with AzPowershell
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
enable-AzPSSession: true
|
||||
- name: Setup git config
|
||||
run: |
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git config --local user.email "<>"
|
||||
- name: Merge master into pull request branch
|
||||
run: |
|
||||
git merge origin/master
|
||||
Conflicts=$(git ls-files -u | wc -l)
|
||||
if [ "$Conflicts" -gt 0 ] ; then
|
||||
echo "There is a merge conflict. Aborting"
|
||||
git merge --abort
|
||||
exit 1
|
||||
fi
|
||||
- name: Run Asim testers
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
inlineScript: |
|
||||
& ".script/tests/asimParsersTest/runAsimTesters.ps1"
|
||||
azPSVersion: "latest"
|
||||
errorActionPreference : continue
|
||||
failOnStandardError: false
|
|
@ -1,58 +1 @@
|
|||
name: Run ASIM testers on "eco-connector-test" workspace
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize, labeled]
|
||||
paths:
|
||||
- 'Parsers/ASimDns/Parsers/**'
|
||||
- 'Parsers/ASimNetworkSession/Parsers/**'
|
||||
- 'Parsers/ASimWebSession/Parsers/**'
|
||||
- 'Parsers/ASimProcessEvent/Parsers/**'
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
runAsimTesters:
|
||||
# The workflow should not run on forked repositories for security reasons
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout pull request branch
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
|
||||
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
|
||||
- name: Login to Azure Public Cloud with AzPowershell
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
enable-AzPSSession: true
|
||||
- name: Setup git config
|
||||
run: |
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git config --local user.email "<>"
|
||||
- name: Merge master into pull request branch
|
||||
run: |
|
||||
git merge origin/master
|
||||
Conflicts=$(git ls-files -u | wc -l)
|
||||
if [ "$Conflicts" -gt 0 ] ; then
|
||||
echo "There is a merge conflict. Aborting"
|
||||
git merge --abort
|
||||
exit 1
|
||||
fi
|
||||
- name: Run Asim testers
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
inlineScript: |
|
||||
& ".script/tests/asimParsersTest/runAsimTesters.ps1"
|
||||
azPSVersion: "latest"
|
||||
errorActionPreference : continue
|
||||
failOnStandardError: false
|
||||
# This workflow is disabled, please use runAsimSchemaAndDataTesters.yaml instead.
|
|
@ -0,0 +1,12 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Kqlvalidations.Tests
|
||||
{
|
||||
public static class CollectionExtensions
|
||||
{
|
||||
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key) where TKey : notnull
|
||||
{
|
||||
return dictionary.TryGetValue(key, out TValue value) ? value : default(TValue);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
{
|
||||
"Name": "apifirewall_log_1_CL",
|
||||
"Properties": [
|
||||
{
|
||||
"Name": "TimeGenerated",
|
||||
"Type": "DateTime"
|
||||
},
|
||||
{
|
||||
"Name": "Timestamp_t",
|
||||
"Type": "DateTime"
|
||||
},
|
||||
{
|
||||
"Name": "Computer",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Computer",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "RawData",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "LogType_d",
|
||||
"Type": "Real"
|
||||
},
|
||||
{
|
||||
"Name": "UUID_g",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Instance_Name_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "API_ID_g",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "API_Name_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Non_blocking_mode_b",
|
||||
"Type": "Bool"
|
||||
},
|
||||
{
|
||||
"Name": "Source_IP_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Source_Port_d",
|
||||
"Type": "Real"
|
||||
},
|
||||
{
|
||||
"Name": "Destination_IP_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Destination_Port_d",
|
||||
"Type": "Real"
|
||||
},
|
||||
{
|
||||
"Name": "Protocol_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Hostname_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "URI_Path_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Method_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Status_d",
|
||||
"Type": "Real"
|
||||
},
|
||||
{
|
||||
"Name": "Query_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Request_Header_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Response_Header_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Errors_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Error_Message_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Error_Step_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "Type",
|
||||
"Type": "String"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"Name": "ForescoutHostProperties_CL",
|
||||
"Properties": [
|
||||
{
|
||||
"Name": "HostProperties_DnsniffEvent_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "HostProperties_Ipv4Addr_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "HostProperties_Ipv6Addr_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "HostProperties_IpAddr_s",
|
||||
"Type": "String"
|
||||
},
|
||||
{
|
||||
"Name": "HostProperties_EmIpAddr_s",
|
||||
"Type": "String"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
"Name": "Watchlist",
|
||||
"Properties": [
|
||||
{
|
||||
"name": "TenantId",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "TimeGenerated",
|
||||
"type": "DateTime"
|
||||
},
|
||||
{
|
||||
"name": "AzureTenantId",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "WatchlistId",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "WatchlistItemId",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "WatchlistName",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "WatchlistAlias",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "Source",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "Provider",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "CreatedBy",
|
||||
"type": "Object"
|
||||
},
|
||||
{
|
||||
"name": "UpdatedBy",
|
||||
"type": "Object"
|
||||
},
|
||||
{
|
||||
"name": "CreatedTimeUTC",
|
||||
"type": "DateTime"
|
||||
},
|
||||
{
|
||||
"name": "LastUpdatedTimeUTC",
|
||||
"type": "DateTime"
|
||||
},
|
||||
{
|
||||
"name": "Notes",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "Tags",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "DefaultDuration",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "TimeToLive",
|
||||
"type": "DateTime"
|
||||
},
|
||||
{
|
||||
"name": "WatchlistItem",
|
||||
"type": "Object"
|
||||
},
|
||||
{
|
||||
"name": "EntityMapping",
|
||||
"type": "Object"
|
||||
},
|
||||
{
|
||||
"name": "CorrelationId",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "SearchKey",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "WatchlistCategory",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "_DTTimestamp",
|
||||
"type": "DateTime"
|
||||
},
|
||||
{
|
||||
"name": "_DTItemId",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "_DTItemType",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "_DTItemStatus",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "SourceSystem",
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "Type",
|
||||
"type": "String"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"Name": "imRegistry",
|
||||
"Properties": [
|
||||
{"Name":"TimeGenerated","Type":"datetime"},
|
||||
{"Name":"_ResourceId","Type":"string"},
|
||||
{"Name":"Type","Type":"string"},
|
||||
{"Name":"EventType","Type":"string"},
|
||||
{"Name":"EventProduct","Type":"string"},
|
||||
{"Name":"EventProductVersion","Type":"string"},
|
||||
{"Name":"EventCount","Type":"int"},
|
||||
{"Name":"EventMessage","Type":"string"},
|
||||
{"Name":"EventVendor","Type":"string"},
|
||||
{"Name":"EventSchemaVersion","Type":"string"},
|
||||
{"Name":"EventOriginalUid","Type":"string"},
|
||||
{"Name":"EventOriginalType","Type":"string"},
|
||||
{"Name":"EventStartTime","Type":"datetime"},
|
||||
{"Name":"EventEndTime","Type":"datetime"},
|
||||
{"Name":"EventReportUrl","Type":"string"},
|
||||
{"Name":"AdditionalFields","Type":"dynamic"},
|
||||
{"Name":"RegistryKey","Type":"string"},
|
||||
{"Name":"RegistryValue","Type":"string"},
|
||||
{"Name":"RegistryValueType","Type":"string"},
|
||||
{"Name":"RegistryValueData","Type":"string"},
|
||||
{"Name":"RegistryPreviousKey","Type":"string"},
|
||||
{"Name":"RegistryPreviousValue","Type":"string"},
|
||||
{"Name":"RegistryPreviousValueType","Type":"string"},
|
||||
{"Name":"RegistryPreviousValueData","Type":"string"},
|
||||
{"Name":"DvcId","Type":"string"},
|
||||
{"Name":"DvcHostname","Type":"string"},
|
||||
{"Name":"DvcIpAddr","Type":"string"},
|
||||
{"Name":"DvcOs","Type":"string"},
|
||||
{"Name":"DvcOsVersion","Type":"string"},
|
||||
{"Name":"DvcMacAddr","Type":"string"},
|
||||
{"Name":"ActorUsername","Type":"string"},
|
||||
{"Name":"ActorUsernameType","Type":"string"},
|
||||
{"Name":"ActorUserId","Type":"string"},
|
||||
{"Name":"ActorUserIdType","Type":"string"},
|
||||
{"Name":"ActorSessionId","Type":"string"},
|
||||
{"Name":"ActingProcessName","Type":"string"},
|
||||
{"Name":"ActingProcessId","Type":"string"},
|
||||
{"Name":"ActingProcessGuid","Type":"string"},
|
||||
{"Name":"ParentProcessName","Type":"string"},
|
||||
{"Name":"ParentProcessId","Type":"string"},
|
||||
{"Name":"ParentProcessGuid","Type":"string"},
|
||||
{"Name":"Dvc","Type":"string"},
|
||||
{"Name":"User","Type":"string"},
|
||||
{"Name":"Process","Type":"string"}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Azure.Sentinel.KustoServices.Contract;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Kqlvalidations.Tests.FunctionSchemasLoaders
|
||||
{
|
||||
public class CommonFunctionsLoader : IFunctionSchemaLoader
|
||||
{
|
||||
public IEnumerable<FunctionSchema> Load()
|
||||
{
|
||||
List<string> commonFunctionsYamlFiles = (new CommonFunctionsYamlFilesLoader()).GetFilesNames();
|
||||
return commonFunctionsYamlFiles.Select(GetFunction).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the fuction's name, parameters and result columns from the yaml file and creates the FunctionSchema.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The parser's yaml file</param>
|
||||
/// <returns>The function schema</returns>
|
||||
private FunctionSchema GetFunction(string fileName)
|
||||
{
|
||||
var deserializer = new DeserializerBuilder().Build();
|
||||
var yaml = deserializer.Deserialize<Dictionary<string, object>> (File.ReadAllText(fileName));
|
||||
return new FunctionSchema((string)yaml["EquivalentBuiltInFunction"], (string)yaml["FunctionQuery"], GetFunctionParameters(yaml));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract fuction parameters from ymal file
|
||||
/// </summary>
|
||||
/// <param name="yaml">The yaml file</param>
|
||||
/// <returns>The function parameters</returns>
|
||||
private List<FunctionParameter> GetFunctionParameters(Dictionary<string, object> yaml)
|
||||
{
|
||||
List<object> functionParameters = (List<object>)yaml.GetValueOrDefault("FunctionParams");
|
||||
return functionParameters?.Select(ConvertObjectToFunctionParameter).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert object to function parameter
|
||||
/// </summary>
|
||||
/// <param name="parameter">The function parameter as an object</param>
|
||||
/// <returns>The function parameter</returns>
|
||||
private FunctionParameter ConvertObjectToFunctionParameter(object parameter)
|
||||
{
|
||||
var dictionary = (Dictionary<object, object>)parameter;
|
||||
return new FunctionParameter()
|
||||
{
|
||||
Name = (string)dictionary["Name"],
|
||||
Type = (string)dictionary["Type"],
|
||||
IsRequired = false,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using Microsoft.Azure.Sentinel.KustoServices.Contract;
|
||||
using Microsoft.Azure.Sentinel.KustoServices.Implementation;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Kqlvalidations.Tests.FunctionSchemasLoaders
|
||||
{
|
||||
/// <summary>
|
||||
/// Manage the supported parameter types
|
||||
/// </summary>
|
||||
public static class TypesDatabase
|
||||
{
|
||||
/// <summary>
|
||||
/// Mapping between the type and its default value
|
||||
/// </summary>
|
||||
public static IReadOnlyDictionary<string, string> TypeToDefaultValueMapping = new Dictionary<string, string>()
|
||||
{
|
||||
{ "string", "" },
|
||||
{ "int", "0" },
|
||||
{ "dynamic", "dynamic([])" },
|
||||
{ "table:(TimeGenerated:datetime)", "range TimeGenerated from ago(3d) to now() step 1d" },
|
||||
};
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ namespace Kqlvalidations.Tests
|
|||
.WithCustomTableSchemasLoader(new CustomJsonDirectoryTablesLoader(Path.Combine(Utils.GetTestDirectory(TestFolderDepth), "CustomTables")))
|
||||
.WithCustomFunctionSchemasLoader(new CustomJsonDirectoryFunctionsLoader(Path.Combine(Utils.GetTestDirectory(TestFolderDepth), "CustomFunctions")))
|
||||
.WithCustomFunctionSchemasLoader(new ParsersCustomJsonDirectoryFunctionsLoader(Path.Combine(Utils.GetTestDirectory(TestFolderDepth), "CustomFunctions")))
|
||||
.WithCustomFunctionSchemasLoader(new CommonFunctionsLoader())
|
||||
.Build();
|
||||
}
|
||||
|
||||
|
@ -127,6 +128,26 @@ namespace Kqlvalidations.Tests
|
|||
ValidateKql(parserName, queryStr);
|
||||
}
|
||||
|
||||
// We pass File name to test because in the result file we want to show an informative name for the test
|
||||
[Theory]
|
||||
[ClassData(typeof(CommonFunctionsYamlFilesTestData))]
|
||||
public void Validate_CommonFunctions_HaveValidKql(string fileName, string encodedFilePath)
|
||||
{
|
||||
Dictionary<object, object> yaml = ReadAndDeserializeYaml(encodedFilePath);
|
||||
var queryParamsAsLetStatements = GenerateFunctionParametersAsLetStatements(yaml, "FunctionParams");
|
||||
|
||||
//Ignore known issues
|
||||
yaml.TryGetValue("Id", out object id);
|
||||
if (id != null && ShouldSkipTemplateValidation((string)id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var queryStr = queryParamsAsLetStatements + (string)yaml["FunctionQuery"];
|
||||
var parserName = (string)yaml["EquivalentBuiltInFunction"];
|
||||
ValidateKql(parserName, queryStr);
|
||||
}
|
||||
|
||||
private void ValidateKql(string id, string queryStr)
|
||||
{
|
||||
var validationResult = _queryValidator.ValidateSyntax(queryStr);
|
||||
|
@ -187,9 +208,9 @@ namespace Kqlvalidations.Tests
|
|||
/// </summary>
|
||||
/// <param name="yaml">The parser's yaml file</param>
|
||||
/// <returns>The function parameters as let statements</returns>
|
||||
private string GenerateFunctionParametersAsLetStatements(Dictionary<object, object> yaml)
|
||||
private string GenerateFunctionParametersAsLetStatements(Dictionary<object, object> yaml, string paramsKey = "ParserParams")
|
||||
{
|
||||
if (yaml.TryGetValue("ParserParams", out object parserParamsObject))
|
||||
if (yaml.TryGetValue(paramsKey, out object parserParamsObject))
|
||||
{
|
||||
var parserParams = (List<object>)parserParamsObject;
|
||||
return string.Join(Environment.NewLine, parserParams.Select(GenerateParamaterAsLetStatement).ToList());
|
||||
|
@ -204,10 +225,11 @@ namespace Kqlvalidations.Tests
|
|||
/// <returns>A function parameter as a let statement</returns>
|
||||
private string GenerateParamaterAsLetStatement(object parameter)
|
||||
{
|
||||
var dictionary = (Dictionary<object, object>)parameter;
|
||||
var dictionary = (IReadOnlyDictionary<object, object>)parameter;
|
||||
string name = (string)dictionary["Name"];
|
||||
string defaultValue = (string)dictionary["Type"] == "string" ? $"'{dictionary["Default"]}'" : (string)dictionary["Default"];
|
||||
return $"let {name}= {defaultValue};";
|
||||
string type = (string)dictionary["Type"];
|
||||
string defaultValue = ((string)dictionary.GetValueOrDefault("Default")) ?? TypesDatabase.TypeToDefaultValueMapping.GetValueOrDefault(type);
|
||||
return $"let {name}= {(type == "string" ? $"'{defaultValue}'" : defaultValue)};";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="YamlDotNet" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Azure.Sentinel.KustoServices" Version="5.1.0" />
|
||||
<PackageReference Include="Microsoft.Azure.Sentinel.KustoServices" Version="5.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичные данные
.script/tests/KqlvalidationsTests/Microsoft.Azure.Sentinel.KustoServices.5.2.0.nupkg
Normal file
Двоичные данные
.script/tests/KqlvalidationsTests/Microsoft.Azure.Sentinel.KustoServices.5.2.0.nupkg
Normal file
Двоичный файл не отображается.
|
@ -9,26 +9,6 @@
|
|||
"templateName": "PotentiallyHarmfulFileTypes.yaml",
|
||||
"validationFailReason": "The name '_GetWatchList' does not refer to any known function"
|
||||
},
|
||||
{
|
||||
"id": "6cb193f3-7c6d-4b53-9153-49a09be830d7",
|
||||
"templateName": "CrashdumpdisabledonhostASIM.yaml",
|
||||
"validationFailReason": "Valid imTable"
|
||||
},
|
||||
{
|
||||
"id": "ac9e233e-44d4-45eb-b522-6e47445f6582",
|
||||
"templateName": "CrashdumpdisabledonhostASIM.yaml",
|
||||
"validationFailReason": "Valid imTable"
|
||||
},
|
||||
{
|
||||
"id": "d3ff27e1-714b-491e-8274-cf34e48cfee5",
|
||||
"templateName": "vimDnsInfobloxNIOS.yaml",
|
||||
"validationFailReason": "The name '_ASIM_ResolveDvcFQDN' does not refer to any known function."
|
||||
},
|
||||
{
|
||||
"id": "678b6e84-0308-461c-ae43-6bb287a9d970",
|
||||
"templateName": "ASimDnsInfobloxNIOS.yaml",
|
||||
"validationFailReason": "The name '_ASIM_ResolveDvcFQDN' does not refer to any known function."
|
||||
},
|
||||
{
|
||||
"id": "55073036-bb86-47d3-a85a-b113ac3d9396",
|
||||
"templateName": "PrivilegedUserLogonfromnewASN.yaml",
|
||||
|
@ -119,6 +99,11 @@
|
|||
"templateName": "vimNetworkSessionMicrosoftMD4IoT.yaml",
|
||||
"validationFailReason": "The name 'LocalPort' does not refer to any known column, table, variable or function."
|
||||
},
|
||||
{
|
||||
"id": "29e99017-e28d-47be-8b9a-c8c711f8a903",
|
||||
"templateName": "NRT_AuthenticationMethodsChangedforVIPUsers.yaml",
|
||||
"validationFailReason": "The name 'User Principal Name' does not refer to any known column, table, variable or function"
|
||||
},
|
||||
{
|
||||
"id": "078a6526-e94e-4cf1-a08e-83bc0186479f",
|
||||
"templateName": "Anomalous AAD Account Manipulation.yaml",
|
||||
|
@ -1168,5 +1153,25 @@
|
|||
"id": "06bc1995-6e36-4cd0-be2b-53789476aec6",
|
||||
"templateName": "AWS_Unused_UnsupportedCloudRegions.yaml",
|
||||
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4f971586-9624-429b-80c4-3c0c940c1962",
|
||||
"templateName": "AzureWAFmatching_log4j_vuln.yaml",
|
||||
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
|
||||
},
|
||||
{
|
||||
"id": "85695071-6425-4ebf-a2f9-e7a827569848",
|
||||
"templateName": "Log4jVulnerableMachines.yaml",
|
||||
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
|
||||
},
|
||||
{
|
||||
"id": "9bbf2a02-a20d-4eaa-ab74-3b60cfe6f3d3",
|
||||
"templateName": "Log4J_IPIOC_Dec112021.yaml",
|
||||
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
|
||||
},
|
||||
{
|
||||
"id": "939d1daa-9ee5-43ae-ae96-12c30c41e528",
|
||||
"templateName": "UserAgentSearch_log4j.yaml",
|
||||
"validationFailReason": "Since the content moved to new location, created dummy file with guidence for redirecting the customers to new location"
|
||||
},
|
||||
]
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Kqlvalidations.Tests
|
||||
{
|
||||
public class CommonFunctionsYamlFilesLoader : YamlFilesLoader
|
||||
{
|
||||
protected override List<string> GetDirectoryPaths()
|
||||
{
|
||||
var basePath = Utils.GetTestDirectory(TestFolderDepth);
|
||||
return new List<string>() { Path.Combine(basePath, "ASIM", "lib", "functions") };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace Kqlvalidations.Tests
|
||||
{
|
||||
public class CommonFunctionsYamlFilesTestData : YamlFilesTestData
|
||||
{
|
||||
public CommonFunctionsYamlFilesTestData() : base(new CommonFunctionsYamlFilesLoader())
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -174,7 +174,7 @@ namespace Kqlvalidations.Tests
|
|||
// Get file present in detection folder or else check in solution analytics rules folder
|
||||
try
|
||||
{
|
||||
detectionsYamlFile = Directory.GetFiles(RootDetectionPaths, detectionsYamlFileName, SearchOption.AllDirectories).Where(s => s.Contains("Detection")).Single();
|
||||
detectionsYamlFile = Directory.GetFiles(RootDetectionPaths, detectionsYamlFileName, SearchOption.AllDirectories).Where(s => s.Contains("\\Detections\\") || s.Contains("/Detections/")).Single();
|
||||
}
|
||||
catch (Exception e) when (e.Message.Contains("Sequence contains no elements"))
|
||||
{
|
||||
|
|
|
@ -203,5 +203,9 @@
|
|||
"4b746dd8-80e6-4f5f-a2a4-881ba9f1ee00",
|
||||
"c9c217f3-1540-4293-b328-d0c5f736244f",
|
||||
"13258fd7-2ee6-4204-b5fb-15c48b5dea49",
|
||||
"06bc1995-6e36-4cd0-be2b-53789476aec6"
|
||||
"06bc1995-6e36-4cd0-be2b-53789476aec6",
|
||||
"4f971586-9624-429b-80c4-3c0c940c1962",
|
||||
"85695071-6425-4ebf-a2f9-e7a827569848",
|
||||
"9bbf2a02-a20d-4eaa-ab74-3b60cfe6f3d3",
|
||||
"939d1daa-9ee5-43ae-ae96-12c30c41e528"
|
||||
]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[
|
||||
"42CrunchAPIProtection",
|
||||
"AIVectraDetect",
|
||||
"AIVectraStream",
|
||||
"AWS",
|
||||
|
@ -127,6 +128,7 @@
|
|||
"RedCanaryDataConnector",
|
||||
"SailPointIdentityNow",
|
||||
"SalesforceServiceCloud",
|
||||
"SAP",
|
||||
"SecurityEvents",
|
||||
"SemperisDSP",
|
||||
"SenservaPro",
|
||||
|
|
|
@ -224,5 +224,15 @@
|
|||
"4b746dd8-80e6-4f5f-a2a4-881ba9f1ee00",
|
||||
"c9c217f3-1540-4293-b328-d0c5f736244f",
|
||||
"13258fd7-2ee6-4204-b5fb-15c48b5dea49",
|
||||
"06bc1995-6e36-4cd0-be2b-53789476aec6"
|
||||
]
|
||||
"06bc1995-6e36-4cd0-be2b-53789476aec6",
|
||||
"610d3850-c26f-4f20-8d86-f10fdf2425f5",
|
||||
"633a91df-d031-4b6e-a413-607a61540559",
|
||||
"2de8abd6-a613-450e-95ed-08e503369fb3",
|
||||
"6e575295-a7e6-464c-8192-3e1d8fd6a990",
|
||||
"3d71fc38-f249-454e-8479-0a358382ef9a",
|
||||
"29283b22-a1c0-4d16-b0a9-3460b655a46a",
|
||||
"4f971586-9624-429b-80c4-3c0c940c1962",
|
||||
"85695071-6425-4ebf-a2f9-e7a827569848",
|
||||
"9bbf2a02-a20d-4eaa-ab74-3b60cfe6f3d3",
|
||||
"939d1daa-9ee5-43ae-ae96-12c30c41e528"
|
||||
]
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"itemsSearchKey": "CallerContext",
|
||||
"rawContent": "CallerContext,SourceSpecificParser\r\nimNone,NoneParser"
|
||||
},
|
||||
"apiVersion": "2021-03-01-preview"
|
||||
"apiVersion": "2022-08-01"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"itemsSearchKey": "SourceType",
|
||||
"rawContent": "SourceType,Source\r\nContosoDns,contoso_machine1"
|
||||
},
|
||||
"apiVersion": "2021-03-01-preview"
|
||||
"apiVersion": "2022-08-01"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -47,7 +47,7 @@ EventMessage,string,Optional,NetworkSession,,,
|
|||
EventCount,int,Mandatory,NetworkSession,,,
|
||||
EventStartTime,datetime,Mandatory,NetworkSession,,,
|
||||
EventEndTime,datetime,Mandatory,NetworkSession,,,
|
||||
EventType,string,Mandatory,NetworkSession,Enumerated,NetworkSession|EndpointNetworkSession|Flow,
|
||||
EventType,string,Mandatory,NetworkSession,Enumerated,NetworkSession|L2NetworkSession|EndpointNetworkSession|Flow,
|
||||
EventSubType,string,Optional,NetworkSession,Enumerated,Start|End|,
|
||||
EventResult,string,Mandatory,NetworkSession,Enumerated,Success|Partial|Failure|NA,
|
||||
EventResultDetails,string,Recommended,NetworkSession,,,
|
||||
|
@ -74,6 +74,13 @@ DvcIdType,string,Conditional,NetworkSession,Enumerated,AzureResourceId|MDEid|MD4
|
|||
DvcMacAddr,string,Optional,NetworkSession,MAC address,,
|
||||
DvcZone,string,Optional,NetworkSession,,,
|
||||
DvcDescription,string,Optional,NetworkSession,,,
|
||||
DvcAction,string,Optional,NetworkSession,,,
|
||||
DvcOs,string,Optional,NetworkSession,,,
|
||||
DvcOsVersion,string,Optional,NetworkSession,,,
|
||||
DvcSubscriptionId,string,Optional,NetworkSession,,,
|
||||
DvcOriginalAction,string,Optional,NetworkSession,,,
|
||||
DvcInterface,string,Optional,NetworkSession,,,
|
||||
DvcAction,string,Optional,NetworkSession,Enumerated,Allow|Deny|Drop|Drop ICMP|Reset|Reset Source|Reset Destination|Encrypt| Decrypt|VPNroute,
|
||||
SrcDescription,string,Optional,NetworkSession,,,
|
||||
DstDescription,string,Optional,NetworkSession,,,
|
||||
ASimMatchingHostname,string,Recommended,NetworkSession,Enumerated,SrcHostname|DstHostname|Both|-,
|
||||
|
@ -91,11 +98,11 @@ DstDeviceType,string,Optional,NetworkSession,Enumerated,Computer|Mobile Device|I
|
|||
DstUserId,string,Optional,NetworkSession,,,
|
||||
DstUserIdType,string,Conditional,NetworkSession,Enumerated,SID|UID|AADID|OktaId|AWSId,DstUserId
|
||||
DstUsername,string,Optional,NetworkSession,Username,,
|
||||
DstSubscriptionId,string,Optional,NetworkSession,,,
|
||||
User,string,Alias,NetworkSession,Username,,DstUsername
|
||||
DstUsernameType,string,Conditional,NetworkSession,Enumerated,UPN|Windows|DN|Simple,DstUsername
|
||||
DstUserType,string,Optional,NetworkSession,Enumerated,Regular|Machine|Admin|System|Application| Service Principal|Other,
|
||||
DstOriginalUserType,string,Optional,NetworkSession,,,
|
||||
DstUserDomain,string,Optional,NetworkSession,,,
|
||||
DstAppName,string,Optional,NetworkSession,,,
|
||||
DstAppId,string,Optional,NetworkSession,,,
|
||||
DstAppType,string,Optional,NetworkSession,Enumerated,Process|Service|Resource|URL|SaaS application|Other,
|
||||
|
@ -125,6 +132,7 @@ SrcUserType,string,Optional,NetworkSession,Enumerated,Regular|Machine|Admin|Syst
|
|||
SrcOriginalUserType,string,Optional,NetworkSession,,,
|
||||
SrcAppName,string,Optional,NetworkSession,,,
|
||||
SrcAppId,string,Optional,NetworkSession,,,
|
||||
SrcSubscriptionId,string,Optional,NetworkSession,,,
|
||||
IpAddr,string,Alias,NetworkSession,IP Address,,SrcIpAddr
|
||||
SrcAppType,string,Optional,NetworkSession,Enumerated,Process|Service|Resource|URL|SaaS application|Other,
|
||||
SrcZone,string,Optional,NetworkSession,,,
|
||||
|
@ -141,6 +149,7 @@ NetworkProtocol,string,Optional,NetworkSession,NetworkProtocol,,
|
|||
NetworkProtocolVersion,string,Optional,NetworkSession,Enumerated,IPv4|IPv6,
|
||||
NetworkDirection,string,Optional,NetworkSession,Enumerated,Inbound|Outbound|Listen|Unknown|Local|External|NA,
|
||||
NetworkDuration,int,Optional,NetworkSession,,,
|
||||
NetworkConnectionHistory,string,Optional,NetworkSession,,,
|
||||
Duration,int,Alias,NetworkSession,,,NetworkDuration
|
||||
NetworkIcmpCode,int,Optional,NetworkSession,,,
|
||||
NetworkIcmpType,string,Optional,NetworkSession,Enumerated,,
|
||||
|
@ -161,12 +170,18 @@ DvcOutboundInterface,string,Optional,NetworkSession,,,
|
|||
NetworkRuleName,string,Optional,NetworkSession,,,
|
||||
NetworkRuleNumber,int,Optional,NetworkSession,,,
|
||||
Rule,string,Optional,NetworkSession,,,
|
||||
DvcAction,string,Optional,NetworkSession,Enumerated,Allow|Deny|Drop|Drop ICMP|Reset|Reset Source|Reset Destination|Encrypt| Decrypt|VPNroute,
|
||||
DvcOriginalAction,string,Optional,NetworkSession,,,
|
||||
ThreatId,string,Optional,NetworkSession,,,
|
||||
ThreatName,string,Optional,NetworkSession,,,
|
||||
ThreatCategory,string,Optional,NetworkSession,,,
|
||||
ThreatRiskLevel,int,Optional,NetworkSession,RiskLevel,,
|
||||
ThreatOriginalRiskLevel,string,Optional,NetworkSession,,,
|
||||
ThreatIpAddr,string,Optional,NetworkSession,IP Address,,
|
||||
ThreatField,string,Optional,NetworkSession,,,
|
||||
ThreatConfidence,int,Optional,NetworkSession,,,
|
||||
ThreatOriginalConfidence,string,Optional,NetworkSession,,,
|
||||
ThreatIsActive,bool,Optional,NetworkSession,,,
|
||||
ThreatFirstReportedTime,datetime,Optional,NetworkSession,,,
|
||||
ThreatLastReportedTime,datetime,Optional,NetworkSession,,,
|
||||
Src,string,Mandatory,NetworkSession,,,
|
||||
Dst,string,Mandatory,NetworkSession,,,
|
||||
ThreatRiskLevelOriginal,string,Optional,NetworkSession,,,
|
||||
|
@ -174,6 +189,12 @@ DstVlanId,string,Optional,NetworkSession,,,
|
|||
OuterVlanId,string,Alias,NetworkSession,,,DstVlanId
|
||||
SrcVlanId,string,Optional,NetworkSession,,,
|
||||
InnerVlanId,string,Alias,NetworkSession,,,SrcVlanId
|
||||
TcpFlagsAck,bool,Optional,NetworkSession,,,
|
||||
TcpFlagsFin,bool,Optional,NetworkSession,,,
|
||||
TcpFlagsPsh,bool,Optional,NetworkSession,,,
|
||||
TcpFlagsRst,bool,Optional,NetworkSession,,,
|
||||
TcpFlagsSyn,bool,Optional,NetworkSession,,,
|
||||
TcpFlagsUrg,bool,Optional,NetworkSession,,,
|
||||
_ResourceId,string,Recommended,Dns,,,
|
||||
AdditionalFields,dynamic,Optional,Dns,,,
|
||||
DnsFlags,string,Optional,Dns,,,
|
||||
|
@ -275,7 +296,6 @@ SrcProcessGuid,string,Optional,Dns,GUID,,
|
|||
SrcProcessId,string,Optional,Dns,,,
|
||||
SrcProcessName,string,Optional,Dns,,,
|
||||
SrcRiskLevel,int,Optional,Dns,,,
|
||||
SrcUserDomain,string,Optional,Dns,,,
|
||||
SrcUserId,string,Optional,Dns,,,
|
||||
SrcUserIdType,string,Conditional,Dns,Enumerated,SID|UIS|AADID|OktaId|AWSId,SrcUserId
|
||||
SrcUsername,string,Optional,Dns,Username,,
|
||||
|
@ -342,7 +362,6 @@ User,string,Alias,WebSession,Username,,SrcUsername
|
|||
DstUsernameType,string,Conditional,WebSession,Enumerated,UPN|Windows|DN|Simple,DstUsername
|
||||
DstUserType,string,Optional,WebSession,Enumerated,Regular|Machine|Admin|System|Application| Service Principal|Other,
|
||||
DstOriginalUserType,string,Optional,WebSession,,,
|
||||
DstUserDomain,string,Optional,WebSession,,,
|
||||
DstAppName,string,Optional,WebSession,,,
|
||||
DstAppId,string,Optional,WebSession,,,
|
||||
DstAppType,string,Optional,WebSession,Enumerated,Process|Service|Resource|URL|SaaS application|Other,
|
||||
|
@ -370,7 +389,6 @@ SrcUsername,string,Optional,WebSession,Username,,
|
|||
SrcUsernameType,string,Conditional,WebSession,Enumerated,UPN|Windows|DN|Simple,SrcUsername
|
||||
SrcUserType,string,Optional,WebSession,Enumerated,Regular|Machine|Admin|System|Application| Service Principal|Other,
|
||||
SrcOriginalUserType,string,Optional,WebSession,,,
|
||||
SrcUserDomain,string,Optional,WebSession,,,
|
||||
SrcAppName,string,Optional,WebSession,,,
|
||||
SrcAppId,string,Optional,WebSession,,,
|
||||
IpAddr,string,Mandatory,WebSession,IP Address,,
|
||||
|
@ -780,4 +798,4 @@ RegistryValueData,string,Recommended,RegistryEvent,,,
|
|||
RegistryValueType,string,Recommended,RegistryEvent,,,
|
||||
User,string,Alias,RegistryEvent,Username,,ActorUsername
|
||||
Type,string,Recommended,ProcessEvent,,,
|
||||
User,string,Alias,ProcessEvent,Username,,TaregetUsername
|
||||
User,string,Alias,ProcessEvent,Username,,TargetUsername
|
||||
|
|
|
|
@ -14,8 +14,8 @@ Description: |
|
|||
FunctionName: ASIM_ResolveDnsQueryType
|
||||
EquivalentBuiltInFunction: _ASIM_ResolveDnsQueryType
|
||||
FunctionParams:
|
||||
- Name: T:(TimeGenerated:datetime)
|
||||
Type: table
|
||||
- Name: T
|
||||
Type: table:(TimeGenerated:datetime)
|
||||
- Name: field
|
||||
Type: string
|
||||
|
||||
|
@ -119,4 +119,3 @@ FunctionQuery: |
|
|||
DnsQueryType between (65280 .. 65534), 'Reserved for Private Use',
|
||||
'Unassigned'
|
||||
)
|
||||
|
|
@ -14,8 +14,8 @@ Description: |
|
|||
FunctionName: ASIM_ResolveDnsResponseCode
|
||||
EquivalentBuiltInFunction: _ASIM_ResolveDnsResponseCode
|
||||
FunctionParams:
|
||||
- Name: T:(TimeGenerated:datetime)
|
||||
Type: table
|
||||
- Name: T
|
||||
Type: table:(TimeGenerated:datetime)
|
||||
- Name: field
|
||||
Type: string
|
||||
|
||||
|
|
|
@ -12,14 +12,14 @@ Description: |
|
|||
FunctionName: ASIM_ResolveDstFQDN
|
||||
EquivalentBuiltInFunction: _ASIM_ResolveDstFQDN
|
||||
FunctionParams:
|
||||
- Name: T:(TimeGenerated:datetime)
|
||||
Type: table
|
||||
- Name: T
|
||||
Type: table:(TimeGenerated:datetime)
|
||||
- Name: field
|
||||
Type: string
|
||||
|
||||
FunctionQuery: |
|
||||
T
|
||||
| invoke ASIM_ResolveFQDN (field)
|
||||
| invoke _ASIM_ResolveFQDN (field)
|
||||
| project-rename
|
||||
DstHostname = ExtractedHostname,
|
||||
DstDomain = Domain,
|
||||
|
|
|
@ -12,14 +12,14 @@ Description: |
|
|||
FunctionName: ASIM_ResolveDvcFQDN
|
||||
EquivalentBuiltInFunction: _ASIM_ResolveDvcFQDN
|
||||
FunctionParams:
|
||||
- Name: T:(TimeGenerated:datetime)
|
||||
Type: table
|
||||
- Name: T
|
||||
Type: table:(TimeGenerated:datetime)
|
||||
- Name: field
|
||||
Type: string
|
||||
|
||||
FunctionQuery: |
|
||||
T
|
||||
| invoke ASIM_ResolveFQDN (field)
|
||||
| invoke _ASIM_ResolveFQDN (field)
|
||||
| project-rename
|
||||
DvcHostname = ExtractedHostname,
|
||||
DvcDomain = Domain,
|
||||
|
|
|
@ -12,8 +12,8 @@ Description: |
|
|||
FunctionName: ASIM_ResolveFQDN
|
||||
EquivalentBuiltInFunction: _ASIM_ResolveFQDN
|
||||
FunctionParams:
|
||||
- Name: T:(TimeGenerated:datetime)
|
||||
Type: table
|
||||
- Name: T
|
||||
Type: table:(TimeGenerated:datetime)
|
||||
- Name: field
|
||||
Type: string
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ Description: |
|
|||
FunctionName: ASIM_ResolveICMPType
|
||||
EquivalentBuiltInFunction: _ASIM_ResolveICMPType
|
||||
FunctionParams:
|
||||
- Name: T:(TimeGenerated:datetime)
|
||||
Type: table
|
||||
- Name: T
|
||||
Type: table:(TimeGenerated:datetime)
|
||||
- Name: field
|
||||
Type: string
|
||||
|
||||
|
@ -77,4 +77,3 @@ FunctionQuery: |
|
|||
NetworkIcmpType != "", NetworkIcmpType,
|
||||
'Unassigned'
|
||||
)
|
||||
|
|
@ -14,8 +14,8 @@ Description: |
|
|||
FunctionName: ASIM_ResolveNetworkProtocol
|
||||
EquivalentBuiltInFunction: _ASIM_ResolveNetworkProtocol
|
||||
FunctionParams:
|
||||
- Name: T:(TimeGenerated:datetime)
|
||||
Type: table
|
||||
- Name: T
|
||||
Type: table:(TimeGenerated:datetime)
|
||||
- Name: field
|
||||
Type: string
|
||||
|
||||
|
@ -178,4 +178,3 @@ FunctionQuery: |
|
|||
NetworkProtocol != "", NetworkProtocol,
|
||||
'Unassigned'
|
||||
)
|
||||
|
|
@ -12,14 +12,14 @@ Description: |
|
|||
FunctionName: ASIM_ResolveSrcFQDN
|
||||
EquivalentBuiltInFunction: _ASIM_ResolveSrcFQDN
|
||||
FunctionParams:
|
||||
- Name: T:(TimeGenerated:datetime)
|
||||
Type: table
|
||||
- Name: T
|
||||
Type: table:(TimeGenerated:datetime)
|
||||
- Name: field
|
||||
Type: string
|
||||
|
||||
FunctionQuery: |
|
||||
T
|
||||
| invoke ASIM_ResolveFQDN (field)
|
||||
| invoke _ASIM_ResolveFQDN (field)
|
||||
| project-rename
|
||||
SrcHostname = ExtractedHostname,
|
||||
SrcDomain = Domain,
|
||||
|
|
Двоичный файл не отображается.
|
@ -3,23 +3,30 @@ import datetime
|
|||
import dateutil
|
||||
import logging
|
||||
import boto3
|
||||
import gzip
|
||||
import io
|
||||
import csv
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import hashlib
|
||||
import hmac
|
||||
import base64
|
||||
import re
|
||||
from threading import Thread
|
||||
from io import StringIO
|
||||
|
||||
import asn1
|
||||
import cffi
|
||||
from boto3.session import Session
|
||||
import azure.functions as func
|
||||
from azure.identity import AzureCliCredential, ChainedTokenCredential, ManagedIdentityCredential, DefaultAzureCredential
|
||||
import botocore
|
||||
|
||||
|
||||
client_id = os.environ.get('ClientID')
|
||||
sentinel_customer_id = os.environ.get('WorkspaceID')
|
||||
sentinel_shared_key = os.environ.get('WorkspaceKey')
|
||||
aws_access_key_id = os.environ.get('AWSAccessKeyId')
|
||||
aws_secret_acces_key = os.environ.get('AWSSecretAccessKey')
|
||||
aws_role_arn = os.environ.get('AWSRoleArn') # Should be full ARN, including AWS account number eg. arn:aws:iam::133761391337:role/AzureSentinelSyncRole
|
||||
aws_role_session_name = os.environ.get('AWSRoleSessionName')
|
||||
aws_region_name = os.environ.get('AWSRegionName')
|
||||
aws_securityhub_filters = os.environ.get('SecurityHubFilters')
|
||||
sentinel_log_type = os.environ.get('LogAnalyticsCustomLogName')
|
||||
|
@ -40,9 +47,20 @@ def main(mytimer: func.TimerRequest) -> None:
|
|||
logging.info('The timer is past due!')
|
||||
|
||||
logging.info('Starting program')
|
||||
# auth to azure ad
|
||||
logging.info ("Authenticating to Azure AD.")
|
||||
try:
|
||||
managed_identity = ManagedIdentityCredential()
|
||||
azure_cli = AzureCliCredential()
|
||||
default_azure_credential = DefaultAzureCredential(exclude_shared_token_cache_credential=True)
|
||||
credential_chain = ChainedTokenCredential(managed_identity, azure_cli, default_azure_credential)
|
||||
token_meta = credential_chain.get_token(client_id)
|
||||
token = token_meta.token
|
||||
except azure.core.exceptions.ClientAuthenticationError as error:
|
||||
logging.info ("Authenticating to Azure AD: %s" % error)
|
||||
|
||||
sentinel = AzureSentinelConnector(logAnalyticsUri, sentinel_customer_id, sentinel_shared_key, sentinel_log_type, queue_size=10000, bulks_number=10)
|
||||
securityHubSession = SecurityHubClient(aws_access_key_id, aws_secret_acces_key, aws_region_name)
|
||||
securityHubSession = SecurityHubClient(aws_role_arn, aws_role_session_name, aws_region_name, token)
|
||||
securityhub_filters_dict = {}
|
||||
logging.info ('SecurityHubFilters : {0}'.format(aws_securityhub_filters))
|
||||
if aws_securityhub_filters:
|
||||
|
@ -64,9 +82,30 @@ def main(mytimer: func.TimerRequest) -> None:
|
|||
for finding in results['Findings']:
|
||||
finding_timestamp = securityHubSession.findingTimestampGenerator(finding['LastObservedAt'])
|
||||
|
||||
if (finding_timestamp > fresh_events_after_this_time):
|
||||
if (finding_timestamp > fresh_events_after_this_time):
|
||||
logging.info ('SecurityHub Finding:{0}'.format(json.dumps(finding)))
|
||||
payload = {}
|
||||
payload.update({'SchemaVersion':finding['SchemaVersion']})
|
||||
payload.update({'Id':finding['Id']})
|
||||
payload.update({'ProductArn':finding['ProductArn']})
|
||||
payload.update({'GeneratorId':finding['GeneratorId']})
|
||||
payload.update({'AwsAccountId':finding['AwsAccountId']})
|
||||
payload.update({'Types':finding['Types']})
|
||||
payload.update({'FirstObservedAt':finding['FirstObservedAt']})
|
||||
payload.update({'LastObservedAt':finding['LastObservedAt']})
|
||||
payload.update({'UpdatedAt':finding['UpdatedAt']})
|
||||
payload.update({'Severity':json.dumps(finding['Severity'], sort_keys=True)})
|
||||
payload.update({'Title':finding['Title']})
|
||||
payload.update({'ProductFields':json.dumps(finding['ProductFields'], sort_keys=True)})
|
||||
payload.update({'ProductArn':finding['ProductArn']})
|
||||
payload.update({'CreatedAt':finding['CreatedAt']})
|
||||
payload.update({'Resources':finding['Resources']})
|
||||
payload.update({'WorkflowState':finding['WorkflowState']})
|
||||
payload.update({'RecordState':finding['RecordState']})
|
||||
|
||||
with sentinel:
|
||||
sentinel.send(finding)
|
||||
sentinel.send(payload)
|
||||
|
||||
failed_sent_events_number = sentinel.failed_sent_events_number
|
||||
successfull_sent_events_number = sentinel.successfull_sent_events_number
|
||||
else:
|
||||
|
@ -85,19 +124,42 @@ def main(mytimer: func.TimerRequest) -> None:
|
|||
if successfull_sent_events_number == 0 and failed_sent_events_number == 0:
|
||||
logging.info('No Fresh SecurityHub Events')
|
||||
|
||||
|
||||
class SecurityHubClient:
|
||||
def __init__(self, aws_access_key_id, aws_secret_acces_key, aws_region_name):
|
||||
self.aws_access_key_id = aws_access_key_id
|
||||
self.aws_secret_acces_key = aws_secret_acces_key
|
||||
self.aws_region_name = aws_region_name
|
||||
def __init__(self, aws_role_arn, aws_role_session_name, aws_region_name, token):
|
||||
|
||||
# define input
|
||||
self.role_arn = aws_role_arn
|
||||
self.role_session_name = aws_role_session_name
|
||||
self.aws_region_name = aws_region_name
|
||||
self.web_identity_token = token
|
||||
|
||||
# create an STS client object that represents a live connection to the STS service
|
||||
sts_client = boto3.client('sts')
|
||||
|
||||
# call assume_role method using input + client
|
||||
try:
|
||||
assumed_role_object=sts_client.assume_role_with_web_identity(
|
||||
RoleArn=self.role_arn,
|
||||
RoleSessionName=self.role_session_name,
|
||||
WebIdentityToken=self.web_identity_token
|
||||
)
|
||||
logging.info ("Successfully assumed role with web identity.")
|
||||
except botocore.exceptions.ClientError as error:
|
||||
logging.info ("Assuming role with web identity failed: %s" % error)
|
||||
|
||||
# from the response, get credentials
|
||||
credentials=assumed_role_object['Credentials']
|
||||
logging.info ('AccessKeyId : {0}'.format(credentials['AccessKeyId']))
|
||||
logging.info ('AssumedRoleArn : {0}'.format(assumed_role_object['AssumedRoleUser']['Arn']))
|
||||
|
||||
# use temp creds to make connection
|
||||
self.securityhub = boto3.client(
|
||||
'securityhub',
|
||||
aws_access_key_id=self.aws_access_key_id,
|
||||
aws_secret_access_key=self.aws_secret_acces_key,
|
||||
aws_access_key_id=credentials['AccessKeyId'],
|
||||
aws_secret_access_key=credentials['SecretAccessKey'],
|
||||
aws_session_token=credentials['SessionToken'],
|
||||
region_name=self.aws_region_name
|
||||
)
|
||||
)
|
||||
|
||||
def freshEventTimestampGenerator(self, freshEventsDuration):
|
||||
tm = datetime.datetime.utcfromtimestamp(time.time())
|
||||
|
@ -225,4 +287,3 @@ class AzureSentinelConnector:
|
|||
middle = int(len(queue) / 2)
|
||||
queues_list = [queue[:middle], queue[middle:]]
|
||||
return self._split_big_request(queues_list[0]) + self._split_big_request(queues_list[1])
|
||||
|
||||
|
|
|
@ -6,3 +6,5 @@
|
|||
## 1.1
|
||||
- Fixed issue with regular expression module
|
||||
|
||||
## 2.0
|
||||
- Added new authentication method, using Azure AD as IdP and the Managed Identity of the function to perform "AssumeRoleWithWebIdentity"
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"AWSTemplateFormatVersion": "2010-09-09",
|
||||
"Description": "Stack to provision resources in AWS for a Security Hub integration.",
|
||||
"Parameters": {
|
||||
"SecurityHubIntegrationRoleName": {
|
||||
"Type": "String",
|
||||
"Description": "Integration role with the required permissions for Security Hub, the default value is recommended.",
|
||||
"AllowedPattern": "[-_a-zA-Z0-9]+",
|
||||
"Default": "SecurityHubIntegrationRole"
|
||||
},
|
||||
"ClientId": {
|
||||
"Type": "String",
|
||||
"Description": "Client ID for the Managed Identity in the Azure Function in the format of a GUID.",
|
||||
"AllowedPattern": "[-_a-zA-Z0-9]+",
|
||||
"Default": "<ClientID>"
|
||||
},
|
||||
"TenantId": {
|
||||
"Type": "String",
|
||||
"Description": "Identity Provider Id in the format of a GUID.",
|
||||
"AllowedPattern": "[-_a-zA-Z0-9]+",
|
||||
"Default": "<TenantID>"
|
||||
},
|
||||
"IdentityProviderThumbprint": {
|
||||
"Type": "String",
|
||||
"Description": "Identity Provider thumbprint.",
|
||||
"AllowedPattern": "[a-zA-Z0-9]+",
|
||||
"Default": "<Thumbprint>"
|
||||
}
|
||||
},
|
||||
"Resources": {
|
||||
"SecurityHubIntegrationOpenIdConnectIdentityProvider": {
|
||||
"Type": "AWS::IAM::OIDCProvider",
|
||||
"Properties": {
|
||||
"ClientIdList": [
|
||||
{ "Ref": "ClientId"}
|
||||
],
|
||||
"ThumbprintList" : [ { "Ref": "IdentityProviderThumbprint" } ],
|
||||
"Url": { "Fn::Sub": "https://sts.windows.net/${TenantId}/" },
|
||||
"Tags" : [ {
|
||||
"Key" : "Name",
|
||||
"Value" : "SecurityHubIntegrationOpenIdConnectIdentityProvider"
|
||||
},
|
||||
{
|
||||
"Key" : "Service",
|
||||
"Value" : "SecurityHubIntegration"
|
||||
}]
|
||||
}
|
||||
},
|
||||
"SecurityHubIntegrationRole": {
|
||||
"Type": "AWS::IAM::Role",
|
||||
"Properties": {
|
||||
"ManagedPolicyArns": [
|
||||
"arn:aws:iam::aws:policy/AWSSecurityHubReadOnlyAccess"
|
||||
],
|
||||
"AssumeRolePolicyDocument": {
|
||||
"Fn::Sub": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::${AWS::AccountId}:oidc-provider/sts.windows.net/${TenantId}/\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"sts.windows.net/${TenantId}/:aud\": \"${ClientId}\"\n }\n }\n }\n ]\n}\n"
|
||||
},
|
||||
"RoleName": {
|
||||
"Ref": "SecurityHubIntegrationRoleName"
|
||||
},
|
||||
"Tags" : [ {
|
||||
"Key" : "Name",
|
||||
"Value" : "SecurityHubIntegrationRole"
|
||||
},
|
||||
{
|
||||
"Key" : "Service",
|
||||
"Value" : "SecurityHubIntegration"
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Outputs": {
|
||||
"SecurityHubIntegrationRoleARN": {
|
||||
"Value": {
|
||||
"Fn::GetAtt": [
|
||||
"SecurityHubIntegrationRole",
|
||||
"Arn"
|
||||
]
|
||||
},
|
||||
"Description": "Security Hub Integration Role ARN."
|
||||
},
|
||||
|
||||
"SecurityHubIntegrationOpenIdConnectIdentityProvider": {
|
||||
"Value": {
|
||||
"Fn::GetAtt": [
|
||||
"SecurityHubIntegrationOpenIdConnectIdentityProvider",
|
||||
"Arn"
|
||||
]
|
||||
},
|
||||
"Description": "Security Hub Integration Open ID Connect Identity Provider ARN."
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
# Ingest AWS Security Hub Events to Azure Sentinel
|
||||
|
||||
Author: Sreedhar Ande
|
||||
|
||||
## Introduction
|
||||
|
||||
AWS SecurityHub is a service that centralizes and organizes alerts and findings from across services. Services include GuardDuty, Macie, IAM Access Analyzer, and AWS Firewall Manager. You can use SecurityHub to continuously monitor your environment and perform automated compliance checks.
|
||||
|
||||
Security Hub is region-specific, which means you need to turn it on and configure it separately for every region in your account.
|
||||
|
@ -8,22 +11,39 @@ Ingest all the SecurityHub findings returned by SecurityHub API, ingests only fr
|
|||
|
||||
## Deploy AWS SecurityHub Data connector
|
||||
|
||||
### Azure
|
||||
|
||||
1. Click "Deploy To Azure" (For both Commercial & Azure GOV)
|
||||
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FDataConnectors%2FAWS-SecurityHubFindings%2Fazuredeploy_awssecurityhub.json)
|
||||
|
||||
2. Select the preferred **Subscription**, **Resource Group** and **Location**
|
||||
**Note**
|
||||
Best practice : Create new Resource Group while deploying - all the resources of your custom Data connector will reside in the newly created Resource
|
||||
Group
|
||||
3. Enter the following value in the ARM template deployment
|
||||
```
|
||||
"Workspace Id": Azure Log Analytics Workspace Id
|
||||
"Workspace Key": Azure Log Analytics Workspace Key
|
||||
"AWS Access Key Id": AWS Access Key
|
||||
"AWS Secret Key ID": AWS Secret Key
|
||||
"AWS Region Name" : AWS SecurityHub Region
|
||||
"CustomLogTableName": Azure Log Analytics Custom Log Table Name
|
||||
```
|
||||
2. Fill in the required fields:
|
||||
```
|
||||
WorkspaceId = Id of the Log Analytics-workspace you want to send logs to.
|
||||
WorkspaceKey = The access key of the Log Analytics-workspace you want to send logs to.
|
||||
AWSRegion = AWS Region your AWS Account is set to.
|
||||
AWSRoleArn = RoleArn is a combination of AWSAccountNumber and RoleName ("arn:aws:iam::<AWSAccountNumber>:role/SecurityHubIntegrationRole").
|
||||
AWSRoleSessionName = Name of the session variable. //Leave default
|
||||
```
|
||||
3. In the function under Settings, go to Identity and turn on Managed Identity.
|
||||
4. Go to Azure AD, Enterprise Applications and find the Managed Identity. Note the ApplicationId (ClientId).
|
||||
5. Under Settings, go to Configuration and paste the ApplicationId (ClientId) into the ClientID parameter.
|
||||
|
||||
### AWS
|
||||
|
||||
1. [Obtain the thumbprint for Azure AD](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html).
|
||||
*The openid endpoint for Azure AD can be found at https://login.microsoftonline.com/$tenantId/v2.0/.well-known/openid-configuration*
|
||||
2. Deploy the [CloudFormation template](https://raw.githubusercontent.com/infernuxmonster/Azure-Sentinel/AWS-SecurityHub-AuthUpgrade/DataConnectors/AWS-SecurityHubFindings/CloudFormation.template.json) and fill in the required fields:
|
||||
```
|
||||
IdP ID (TenantId)
|
||||
ClientID (ApplicationId of the Managed Identity created for the Azure Function)
|
||||
Thumbprint (Obtained in step 1)
|
||||
```
|
||||
Leave everything else to default.
|
||||
|
||||
### Azure
|
||||
|
||||
1. For the first time run, change the FreshEventTimeStamp variable in configuration to a higher value (in minutes) to populate the log - recommended 3600.
|
||||
2. After the function runs, change the above value back to 10.
|
||||
|
||||
## Post Deployment Steps
|
||||
|
||||
|
@ -34,7 +54,7 @@ Ingest all the SecurityHub findings returned by SecurityHub API, ingests only fr
|
|||
c. Click on "Schedule" under "Application Settings"
|
||||
d. Update your own schedule using cron expression.
|
||||
```
|
||||
**Note: For a `TimerTrigger` to work, you provide a schedule in the form of a [cron expression](https://en.wikipedia.org/wiki/Cron#CRON_expression)(See the link for full details). A cron expression is a string with 6 separate expressions which represent a given schedule via patterns. The pattern we use to represent every 10 minutes is `0 */10 * * * *`. This, in plain text, means: "When seconds is equal to 0, minutes is divisible by 10, for any hour, day of the month, month, day of the week, or year".**
|
||||
**Note: For a `TimerTrigger` to work, you provide a schedule in the form of a [cron expression](https://en.wikipedia.org/wiki/Cron#CRON_expression)(See the link for full details). A cron expression is a string with 6 separate expressions which represent a given schedule via patterns. The pattern we use to represent every 10 minutes is `0 */10 * * * *`. This, in plain text, means: "When seconds is equal to 0, minutes is divisible by 10, for any hour, day of the month, month, day of the week, or year".**
|
||||
|
||||
2. Parameterized finding attributes using a environment variable "SecurityHubFilters" which is used to define a condition to filter the returned findings. You can filter by up to 10 finding attributes. For each attribute, you can provide up to 20 filter values.
|
||||
```
|
||||
|
@ -73,7 +93,7 @@ Ingest all the SecurityHub findings returned by SecurityHub API, ingests only fr
|
|||
Schedule=0 */30 * * * *
|
||||
|
||||
|
||||
4. AWSAccessKey, AWSSecretAccessKey and Workspace Key will be placed as "Secrets" in the Azure KeyVault `awssecurityhub<<uniqueid>>` with only Azure Function access policy. If you want to see/update these secrets,
|
||||
4. All secrets will be placed as "Secrets" in the Azure KeyVault `awssecurityhub<<uniqueid>>` with only Azure Function access policy. If you want to see/update these secrets,
|
||||
|
||||
```
|
||||
a. Go to Azure KeyVault "awssecurityhub<<uniqueid>>"
|
||||
|
|
|
@ -14,21 +14,21 @@
|
|||
"type": "securestring",
|
||||
"defaultValue": ""
|
||||
},
|
||||
"AWSAccessKeyId": {
|
||||
"AWSRoleSessionName": {
|
||||
"type": "string",
|
||||
"defaultValue": "<AWSAccessKeyId>"
|
||||
"defaultValue": "AWSSecurityHub2Sentinel"
|
||||
},
|
||||
"AWSSecretAccessKey": {
|
||||
"type": "securestring",
|
||||
"defaultValue": ""
|
||||
"AWSRoleArn": {
|
||||
"type": "string",
|
||||
"defaultValue": "arn:aws:iam::<AWSAccountNumber>:role/SecurityHubIntegrationRole"
|
||||
},
|
||||
"AWSRegionName": {
|
||||
"type": "string",
|
||||
"defaultValue": "<AWSRegionName>"
|
||||
"defaultValue": "eu-central-1"
|
||||
},
|
||||
"LogAnalyticsCustomLogName": {
|
||||
"LogAnalyticsCustomLogName": {
|
||||
"type": "string",
|
||||
"defaultValue": "<LogAnalyticsCustomLogName>"
|
||||
"defaultValue": "AWSSecurityHubFindings_CL"
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
|
@ -36,8 +36,7 @@
|
|||
"StorageAccountName":"[concat(substring(variables('FunctionName'), 0, 20), 'sa')]",
|
||||
"KeyVaultName": "[concat(substring(variables('FunctionName'), 0, 20), 'kv')]",
|
||||
"LogAnalyticsWorkspaceKey": "LogAnalyticsWorkspaceKey",
|
||||
"AWSAccessKeyId":"AWSAccessKeyId",
|
||||
"AWSSecretAccessKey":"AWSSecretAccessKey",
|
||||
"AWSRoleArn":"AWSRoleArn",
|
||||
"StorageSuffix":"[environment().suffixes.storage]",
|
||||
"LogAnaltyicsUri":"[replace(environment().portal, 'https://portal', concat('https://', toLower(parameters('WorkspaceId')), '.ods.opinsights'))]"
|
||||
},
|
||||
|
@ -142,7 +141,7 @@
|
|||
"clientAffinityEnabled": true,
|
||||
"alwaysOn": true,
|
||||
"reserved": true
|
||||
},
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2018-11-01",
|
||||
|
@ -151,9 +150,8 @@
|
|||
"dependsOn": [
|
||||
"[concat('Microsoft.Web/sites/', variables('FunctionName'))]",
|
||||
"[resourceId('Microsoft.KeyVault/vaults/', variables('KeyVaultName'))]",
|
||||
"[resourceId('Microsoft.KeyVault/vaults/secrets', variables('KeyVaultName'), variables('AWSAccessKeyId'))]",
|
||||
"[resourceId('Microsoft.KeyVault/vaults/secrets', variables('KeyVaultName'), variables('LogAnalyticsWorkspaceKey'))]",
|
||||
"[resourceId('Microsoft.KeyVault/vaults/secrets', variables('KeyVaultName'), variables('AWSSecretAccessKey'))]"
|
||||
"[resourceId('Microsoft.KeyVault/vaults/secrets', variables('KeyVaultName'), variables('AWSRoleArn'))]",
|
||||
"[resourceId('Microsoft.KeyVault/vaults/secrets', variables('KeyVaultName'), variables('LogAnalyticsWorkspaceKey'))]"
|
||||
],
|
||||
"properties": {
|
||||
"FUNCTIONS_EXTENSION_VERSION": "~3",
|
||||
|
@ -163,15 +161,18 @@
|
|||
"AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', toLower(variables('StorageAccountName')),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName')), '2019-06-01').keys[0].value, ';EndpointSuffix=',toLower(variables('StorageSuffix')))]",
|
||||
"WorkspaceID": "[parameters('WorkspaceID')]",
|
||||
"WorkspaceKey": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('LogAnalyticsWorkspaceKey')).secretUriWithVersion, ')')]",
|
||||
"AWSAccessKeyId": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('AWSAccessKeyId')).secretUriWithVersion, ')')]",
|
||||
"AWSSecretAccessKey": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('AWSSecretAccessKey')).secretUriWithVersion, ')')]",
|
||||
"AWSRoleSessionName": "[parameters('AWSRoleSessionName')]",
|
||||
"AWSRoleArn": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('AWSRoleArn')).secretUriWithVersion, ')')]",
|
||||
"AWSRegionName": "[parameters('AWSRegionName')]",
|
||||
"LogAnalyticsCustomLogName":"[parameters('LogAnalyticsCustomLogName')]",
|
||||
"Schedule":"0 */10 * * * *",
|
||||
"Schedule":"*/10 * * * *",
|
||||
"FreshEventTimeStamp":"10",
|
||||
"SecurityHubFilters":"",
|
||||
"SecurityHubFilters":"{'SeverityLabel': [{'Value': 'HIGH', 'Comparison': 'EQUALS'},{'Value': 'CRITICAL', 'Comparison': 'EQUALS'},],'RecordState': [{'Value': 'ACTIVE', 'Comparison': 'EQUALS'}]}",
|
||||
"LAURI": "[variables('LogAnaltyicsUri')]",
|
||||
"WEBSITE_RUN_FROM_PACKAGE": "https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AWS-SecurityHubFindings/AzFunAWSSecurityHubIngestion.zip?raw=true"
|
||||
"WEBSITE_RUN_FROM_PACKAGE": "https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AWS-SecurityHubFindings/AzFunAWSSecurityHubIngestion.zip?raw=true",
|
||||
"ClientID":"",
|
||||
"SCM_DO_BUILD_DURING_DEPLOYMENT": "true",
|
||||
"ENABLE_ORYX_BUILD": "true"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -210,33 +211,18 @@
|
|||
{
|
||||
"type": "secrets",
|
||||
"apiVersion": "2016-10-01",
|
||||
"name": "[variables('AWSAccessKeyId')]",
|
||||
"name": "[variables('AWSRoleArn')]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.KeyVault/vaults/', variables('KeyVaultName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"value": "[parameters('AWSAccessKeyId')]",
|
||||
"value": "[parameters('AWSRoleArn')]",
|
||||
"contentType": "string",
|
||||
"attributes": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "secrets",
|
||||
"apiVersion": "2016-10-01",
|
||||
"name": "[variables('AWSSecretAccessKey')]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.KeyVault/vaults/', variables('KeyVaultName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"value": "[parameters('AWSSecretAccessKey')]",
|
||||
"contentType": "string",
|
||||
"attributes": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "secrets",
|
||||
"apiVersion": "2016-10-01",
|
||||
|
@ -291,4 +277,4 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,22 @@
|
|||
# The Python Worker is managed by Azure Functions platform
|
||||
# Manually managing azure-functions-worker may cause unexpected issues
|
||||
|
||||
azure-functions
|
||||
azure-functions==1.8.0
|
||||
boto3==1.9.180
|
||||
requests==2.22.0
|
||||
requests==2.22.0
|
||||
adal==1.2.2
|
||||
aiohttp==3.7.4
|
||||
asn1crypto==0.24.0
|
||||
azure-common==1.1.24
|
||||
azure-core==1.21.0
|
||||
botocore==1.12.10
|
||||
cryptography==3.3.2
|
||||
pyasn1==0.4.2
|
||||
pyasn1-modules==0.2.1
|
||||
cffi==1.5.2
|
||||
pyOpenSSL==17.5.0
|
||||
pycrypto==2.6.1
|
||||
version-utils==0.2.2
|
||||
wheel==0.24.0
|
||||
zope.interface==4.1.1
|
||||
azure-identity==1.7.1
|
||||
|
|
|
@ -50,6 +50,14 @@ entityMappings:
|
|||
customDetails:
|
||||
IpAddresses: IpAddresses
|
||||
ReportedBy: ReportedBy
|
||||
|
||||
version: 1.2.1
|
||||
version: 1.2.2
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Ofer Shezaf
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -36,5 +36,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.1.1
|
||||
kind: Scheduled
|
||||
version: 1.1.2
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Ofer Shezaf
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -36,5 +36,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: AccountCustomEntity
|
||||
version: 1.2.1
|
||||
kind: Scheduled
|
||||
version: 1.2.2
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Ofer Shezaf
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Network" ]
|
|
@ -49,5 +49,8 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
version: 1.0.2
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
|
@ -59,5 +59,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.3.1
|
||||
kind: Scheduled
|
||||
version: 1.3.3
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yaron
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Network" ]
|
|
@ -73,5 +73,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.3.1
|
||||
kind: Scheduled
|
||||
version: 1.3.2
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yaron
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Network" ]
|
|
@ -49,5 +49,14 @@ entityMappings:
|
|||
columnName: AlgorithmCustomEntity
|
||||
- identifier: Value
|
||||
columnName: FileHashCustomEntity
|
||||
version: 1.0.4
|
||||
version: 1.0.5
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yaron
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Intelligence" ]
|
|
@ -48,5 +48,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Name
|
||||
columnName: FileName
|
||||
version: 1.1.2
|
||||
version: 1.1.3
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Ajeet Prakash
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Intelligence" ]
|
|
@ -37,5 +37,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: HostName
|
||||
columnName: DvcHostname
|
||||
version: 1.0.2
|
||||
version: 1.0.3
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection" ]
|
|
@ -54,5 +54,14 @@ entityMappings:
|
|||
columnName: AlgorithmCustomEntity
|
||||
- identifier: Value
|
||||
columnName: FileHashCustomEntity
|
||||
version: 1.1.2
|
||||
kind: Scheduled
|
||||
version: 1.1.3
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yuval Naor
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Intelligence" ]
|
|
@ -49,5 +49,14 @@ entityMappings:
|
|||
columnName: AlgorithmCustomEntity
|
||||
- identifier: Value
|
||||
columnName: FileHashCustomEntity
|
||||
version: 1.1.2
|
||||
version: 1.1.3
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yuval Naor
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - 0-day Vulnerability" ]
|
|
@ -44,5 +44,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Url
|
||||
columnName: RequestURL
|
||||
version: 1.1.1
|
||||
version: 1.1.2
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection" ]
|
|
@ -54,5 +54,14 @@ customDetails:
|
|||
alertDetailsOverride:
|
||||
alertDisplayNameFormat: Excessive number of HTTP authentication failures from {{SrcIpAddr}
|
||||
alertDescriptionFormat: A client with address {{SrcIpAddr}} generated a large number of failed authentication HTTP requests. This may indicate a [brute force](https://en.wikipedia.org/wiki/Brute-force_attack) or [credential stuffing](https://en.wikipedia.org/wiki/Credential_stuffing) attack.
|
||||
version: 1.0.2
|
||||
version: 1.0.3
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yaron
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -112,5 +112,14 @@ customDetails:
|
|||
DGAPattern: DGADomain
|
||||
NameCount: NameCount
|
||||
|
||||
version: 1.1.1
|
||||
version: 1.1.2
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yaron
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection" ]
|
|
@ -54,5 +54,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Url
|
||||
columnName: UrlCustomEntity
|
||||
version: 1.1.0
|
||||
version: 1.1.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yaron
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -55,6 +55,14 @@ customDetails:
|
|||
|
||||
eventGroupingSettings:
|
||||
aggregationKind: AlertPerResult
|
||||
|
||||
version: 1.1.0
|
||||
kind: Scheduled
|
||||
version: 1.1.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yaron
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection" ]
|
|
@ -55,6 +55,14 @@ customDetails:
|
|||
|
||||
eventGroupingSettings:
|
||||
aggregationKind: AlertPerResult
|
||||
|
||||
version: 1.1.0
|
||||
kind: Scheduled
|
||||
version: 1.1.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yaron
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection" ]
|
|
@ -57,5 +57,14 @@ customDetails:
|
|||
|
||||
eventGroupingSettings:
|
||||
aggregationKind: AlertPerResult
|
||||
version: 1.1.0
|
||||
version: 1.1.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Yaron
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection" ]
|
||||
|
|
|
@ -41,5 +41,14 @@ alertDetailsOverride:
|
|||
alertTacticsColumnName: Tactics
|
||||
sentinelEntitiesMappings:
|
||||
- columnName: Entities
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Jose Sebastian Canos
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -47,5 +47,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: ElevatedBy
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection" ]
|
|
@ -39,5 +39,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: userPrincipalName
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection", "Identity" ]
|
|
@ -43,5 +43,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Url
|
||||
columnName: NewURI
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -58,5 +58,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: ipAddress
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -40,5 +40,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -48,5 +48,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Url
|
||||
columnName: NewURL
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -42,5 +42,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: AddedUser
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -35,5 +35,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: ipAddress
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -47,5 +47,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: ipAddress
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -45,5 +45,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: userPrincipalName
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -0,0 +1,53 @@
|
|||
id: 6ab1f7b2-61b8-442f-bc81-96afe7ad8c53
|
||||
name: Guest accounts added in AAD Groups other than the ones specified
|
||||
description: |
|
||||
'Guest Accounts are added in the Organization Tenants to perform various tasks i.e projects execution, support etc.. This detection notifies when guest users are added to Azure AD Groups other than the ones specified and poses a risk to gain access to sensitive apps or data.'
|
||||
severity: High
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureActiveDirectory
|
||||
dataTypes:
|
||||
- AuditLogs
|
||||
queryFrequency: 5m
|
||||
queryPeriod: 1d
|
||||
triggerOperator: gt
|
||||
triggerThreshold: 0
|
||||
status: Available
|
||||
tactics:
|
||||
- InitialAccess
|
||||
- Persistence
|
||||
- Discovery
|
||||
relevantTechniques:
|
||||
- T1078.004
|
||||
- T1136.003
|
||||
- T1087.004
|
||||
query: |
|
||||
// OBJECT ID of AAD Groups can be found by navigating to Azure Active Directory then from menu on the left, select Groups and from the list shown of AAD Groups, the Second Column shows the ObjectID of each
|
||||
let queryperiod= 1d;
|
||||
let GroupIDs = dynamic(["List with Custom AAD GROUP OBJECT ID 1","Custom AAD GROUP OBJECT ID 2"]);
|
||||
AuditLogs
|
||||
| where TimeGenerated > ago(queryperiod)
|
||||
| where OperationName in ('Add member to group', 'Add owner to group')
|
||||
| extend InitiatedByActionUserInformation = iff(isnotempty(InitiatedBy.user.userPrincipalName), InitiatedBy.user.userPrincipalName, InitiatedBy.app.displayName)
|
||||
| extend InitiatedByIPAdress = InitiatedBy.user.ipAddress
|
||||
// Uncomment the following line to filter events where the inviting user was a guest user
|
||||
//| where InitiatedBy has_any ("CUSTOM DOMAIN NAME#", "#EXT#")
|
||||
| extend InvitedUser = TargetResources[0].userPrincipalName
|
||||
| extend AADGroup = TargetResources[0].modifiedProperties[1].newValue
|
||||
| where InvitedUser has_any ("CUSTOM DOMAIN NAME#", "#EXT#")
|
||||
| mv-expand AADGroup = TargetResources[1].id to typeof(string)
|
||||
| where AADGroup !in (GroupIDs)
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: InvitedUser
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: Name
|
||||
columnName: InitiatedByActionUserInformation
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: InitiatedByIPAdress
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
|
@ -49,5 +49,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: ipAddress
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -0,0 +1,51 @@
|
|||
id: 639aa695-9de9-4921-aa6b-6fdc35cb1eee
|
||||
name: Guest accounts changed user type from guest to members in AzureAD
|
||||
description: |
|
||||
'Guest Accounts are added in the Organization Tenants to perform various tasks i.e projects execution, support etc.. This detection notifies when guest users are changed from user type as should be in AzureAD to member and gain other rights in the tenant.'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureActiveDirectory
|
||||
dataTypes:
|
||||
- AuditLogs
|
||||
queryFrequency: 1d
|
||||
queryPeriod: 1d
|
||||
triggerOperator: gt
|
||||
triggerThreshold: 0
|
||||
status: Available
|
||||
tactics:
|
||||
- InitialAccess
|
||||
- Persistence
|
||||
- Discovery
|
||||
relevantTechniques:
|
||||
- T1078.004
|
||||
- T1136.003
|
||||
- T1087.004
|
||||
query: |
|
||||
AuditLogs
|
||||
| where OperationName contains "Update user"
|
||||
| where TargetResources[0].modifiedProperties[0].oldValue contains "Guest"
|
||||
| extend InvitedUser = TargetResources[0].userPrincipalName
|
||||
// Uncomment the below line if you want to get alerts for changed usertype from specific domains or users
|
||||
//| where InvitedUser has_any ("CUSTOM DOMAIN NAME#", "#EXT#")
|
||||
| extend InitiatedByActionUserInformation = iff(isnotempty(InitiatedBy.user.userPrincipalName), InitiatedBy.user.userPrincipalName, InitiatedBy.app.displayName)
|
||||
| extend InitiatedByIPAdress = InitiatedBy.user.ipAddress
|
||||
| extend OldUserType = TargetResources[0].modifiedProperties[0].oldValue contains "Guest"
|
||||
| extend NewUserType = TargetResources[0].modifiedProperties[0].newValue contains "Member"
|
||||
| mv-expand OldUserType = TargetResources[0].modifiedProperties[0].oldValue to typeof(string)
|
||||
| mv-expand NewUserType = TargetResources[0].modifiedProperties[0].newValue to typeof(string)
|
||||
| where OldUserType != NewUserType
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: InvitedUser
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: Name
|
||||
columnName: InitiatedByActionUserInformation
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: InitiatedByIPAdress
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
|
@ -0,0 +1,37 @@
|
|||
id: 29e99017-e28d-47be-8b9a-c8c711f8a903
|
||||
name: NRT Authentication Methods Changed for VIP Users
|
||||
description: |
|
||||
'Identifies authentication methods being changed for a list of VIP users watchlist. This could be an indication of an attacker adding an auth method to the account so they can have continued access.'
|
||||
severity: Medium
|
||||
requiredDataConnectors:
|
||||
- connectorId: AzureActiveDirectory
|
||||
dataTypes:
|
||||
- AuditLogs
|
||||
tactics:
|
||||
- Persistence
|
||||
relevantTechniques:
|
||||
- T1098
|
||||
tags:
|
||||
- AADSecOpsGuide
|
||||
query: |
|
||||
let security_info_actions = dynamic(["User registered security info", "User changed default security info", "User deleted security info", "Admin updated security info", "User reviewed security info", "Admin deleted security info", "Admin registered security info"]);
|
||||
let VIPUsers = (_GetWatchlist('VIPUsers') | distinct ["User Principal Name"]);
|
||||
AuditLogs
|
||||
| where Category =~ "UserManagement"
|
||||
| where ActivityDisplayName in (security_info_actions)
|
||||
| extend Initiator = tostring(InitiatedBy.user.userPrincipalName)
|
||||
| extend IP = tostring(InitiatedBy.user.ipAddress)
|
||||
| extend Target = tolower(tostring(TargetResources[0].userPrincipalName))
|
||||
| where Target in (VIPUsers)
|
||||
| summarize Start=min(TimeGenerated), End=max(TimeGenerated), Actions = make_set(ResultReason) by Initiator, IP, Result, Target
|
||||
entityMappings:
|
||||
- entityType: Account
|
||||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: Targets
|
||||
- entityType: IP
|
||||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IP
|
||||
version: 1.0.0
|
||||
kind: NRT
|
|
@ -52,5 +52,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: AddedBy
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -50,5 +50,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: AadUserId
|
||||
columnName: SPID
|
||||
version: 1.0.1
|
||||
version: 1.0.2
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -53,5 +53,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: AddedBy
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -44,5 +44,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPAddress
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Ashwin Patil
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -71,5 +71,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: ipAddress
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -43,5 +43,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: AddedUser
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -35,5 +35,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: AddedUser
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -42,5 +42,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: UpdatedUserPrincipalName
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -60,5 +60,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: CreatedUserPrincipalName
|
||||
version: 1.0.1
|
||||
version: 1.0.2
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -51,5 +51,16 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: NRT
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Samik Roy
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
||||
threatAnalysisTactics: [ "DefenseEvasion" ]
|
||||
threatAnalysisTechniques: [ "T1550.001" ]
|
|
@ -39,5 +39,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: CallerIpAddress
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: KennethMLdk
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Platform" ]
|
|
@ -98,6 +98,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: HostName
|
||||
columnName: HostCustomEntity
|
||||
version: 1.0.3
|
||||
version: 1.0.4
|
||||
kind: Scheduled
|
||||
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Identity" ]
|
|
@ -19,5 +19,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: HostCustomEntity
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: SecurityJedi
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Platform" ]
|
|
@ -19,5 +19,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: FullName
|
||||
columnName: HostCustomEntity
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: SecurityJedi
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Platform" ]
|
|
@ -0,0 +1,4 @@
|
|||
id: 4f971586-9624-429b-80c4-3c0c940c1962
|
||||
name: Azure WAF matching for Log4j vuln(CVE-2021-44228)
|
||||
description: |
|
||||
'As part of content migration, this file is moved to a new location. You can find it here https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Apache%20Log4j%20Vulnerability%20Detection'
|
|
@ -50,5 +50,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: clientIp_s
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: shabaz-github
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection", "Platform" ]
|
|
@ -47,5 +47,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: clientIp_s
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: shabaz-github
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Threat Protection", "Platform" ]
|
|
@ -46,5 +46,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: HostName
|
||||
columnName: SourceHostName
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Thomas McElroy
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -43,5 +43,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: HostName
|
||||
columnName: SourceHostName
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Thomas McElroy
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -52,5 +52,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Url
|
||||
columnName: RequestURL
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Thomas McElroy
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -121,5 +121,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: DomainName
|
||||
columnName: Name
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: robMSFT
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -82,5 +82,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Ashwin Patil
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -30,5 +30,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Jordan Ross
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others", "Networking" ]
|
|
@ -33,5 +33,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: HostName
|
||||
columnName: DeviceName
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: Pete Bryan
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
|
@ -25,5 +25,14 @@ entityMappings:
|
|||
fieldMappings:
|
||||
- identifier: Address
|
||||
columnName: IPCustomEntity
|
||||
version: 1.0.0
|
||||
kind: Scheduled
|
||||
version: 1.0.1
|
||||
kind: Scheduled
|
||||
metadata:
|
||||
source:
|
||||
kind: Community
|
||||
author:
|
||||
name: SecurityJedi
|
||||
support:
|
||||
tier: Community
|
||||
categories:
|
||||
domains: [ "Security - Others" ]
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче