diff --git a/DataConnectors/AWS-S3/ConfigAwsS3DataConnectorScripts.zip b/DataConnectors/AWS-S3/ConfigAwsS3DataConnectorScripts.zip index b4ae7dfa52..f1264dda43 100644 Binary files a/DataConnectors/AWS-S3/ConfigAwsS3DataConnectorScripts.zip and b/DataConnectors/AWS-S3/ConfigAwsS3DataConnectorScripts.zip differ diff --git a/DataConnectors/AWS-S3/ConfigGuardDutyDataConnector.ps1 b/DataConnectors/AWS-S3/ConfigGuardDutyDataConnector.ps1 index 423422932a..83e611c537 100644 --- a/DataConnectors/AWS-S3/ConfigGuardDutyDataConnector.ps1 +++ b/DataConnectors/AWS-S3/ConfigGuardDutyDataConnector.ps1 @@ -139,17 +139,25 @@ function Get-GuardDutyAndRoleKmsPolicy return $kmsPolicy.Replace("'",'"') } -function Enable-GuardDuty +function Enable-GuardDuty-ForRegion { <# .SYNOPSIS Enables GuardDuty based on specified configuration + .PARAMETER Region + Specifies the region #> - Write-Log -Message "Enabling GuardDuty" -LogFileName $LogFileName -LinePadding 1 + param ( + [Parameter()] + [ValidateNotNullOrEmpty()][string] + $Region + ) + + Write-Log -Message "Enabling GuardDuty for region $region" -LogFileName $LogFileName -LinePadding 1 Set-RetryAction({ Write-Log -Message "Executing: aws guardduty create-detector --enable --finding-publishing-frequency FIFTEEN_MINUTES 2>&1" -LogFileName $LogFileName -Severity Verbose - $newGuarduty = aws guardduty create-detector --enable --finding-publishing-frequency FIFTEEN_MINUTES 2>&1 + $newGuarduty = aws --region $region guardduty create-detector --enable --finding-publishing-frequency FIFTEEN_MINUTES 2>&1 $isGuardutyEnabled = $lastexitcode -ne 0 if ($isGuardutyEnabled) @@ -157,10 +165,8 @@ function Enable-GuardDuty Write-Output `n Write-Log -Message 'A detector already exists for the current account.' -LogFileName $LogFileName Write-Log -Message "Executing: aws guardduty list-detectors" -LogFileName $LogFileName -Severity Verbose - $detectors = (aws guardduty list-detectors | ConvertFrom-Json)."DetectorIds" -join ', ' - Write-Log -Message "List of existing detectors: $detectors" -LogFileName $LogFileName - - $script:detectorId = Read-ValidatedHost 'Please enter detector Id from the above list' + + $script:detectorId = (aws --region $region guardduty list-detectors | ConvertFrom-Json)."DetectorIds" -join ', ' Write-Log -Message "Detector Id: $detectorId" -LogFileName $LogFileName } else @@ -169,7 +175,7 @@ function Enable-GuardDuty } Write-Log -Message "Executing: aws guardduty list-publishing-destinations --detector-id $detectorId 2>&1" -LogFileName $LogFileName -Severity Verbose - $script:currentDestinations = aws guardduty list-publishing-destinations --detector-id $detectorId 2>&1 + $script:currentDestinations = aws --region $region guardduty list-publishing-destinations --detector-id $detectorId 2>&1 Write-Log $currentDestinations -LogFileName $LogFileName -Severity Verbose }) } @@ -179,19 +185,27 @@ function Set-GuardDutyPublishDestinationBucket <# .SYNOPSIS Configures GuardDuty to publish logs to destination bucket + .PARAMETER Region + Specifies the region #> + param ( + [Parameter()] + [ValidateNotNullOrEmpty()][string] + $Region + ) + $currentDestinationsObject = $currentDestinations | ConvertFrom-Json $currentS3Destinations = $currentDestinationsObject.Destinations | Where-Object DestinationType -eq S3 if ($null -eq $currentS3Destinations) { Write-Log -Message "Executing: aws guardduty create-publishing-destination --detector-id $detectorId --destination-type S3 --destination-properties DestinationArn=arn:aws:s3:::$bucketName,KmsKeyArn=$kmsArn | Out-Null" -LogFileName $LogFileName -Severity Verbose - aws guardduty create-publishing-destination --detector-id $detectorId --destination-type S3 --destination-properties DestinationArn=arn:aws:s3:::$bucketName,KmsKeyArn=$kmsArn | Out-Null + aws --region $Region guardduty create-publishing-destination --detector-id $detectorId --destination-type S3 --destination-properties DestinationArn=arn:aws:s3:::$bucketName,KmsKeyArn=$kmsArn | Out-Null } else { Write-Log "Executing: aws guardduty describe-publishing-destination --detector-id $detectorId --destination-id $currentS3Destinations.DestinationId | ConvertFrom-Json" -LogFileName $LogFileName -Severity Verbose - $destinationDescriptionObject = aws guardduty describe-publishing-destination --detector-id $detectorId --destination-id $currentS3Destinations.DestinationId | ConvertFrom-Json + $destinationDescriptionObject = aws --region $Region guardduty describe-publishing-destination --detector-id $detectorId --destination-id $currentS3Destinations.DestinationId | ConvertFrom-Json $destinationArn = $destinationDescriptionObject.DestinationProperties.DestinationArn Write-Log -Message "GuardDuty is already configured for bucket arn '$destinationArn'" -LogFileName $LogFileName -LinePadding 2 @@ -199,7 +213,7 @@ function Set-GuardDutyPublishDestinationBucket if ($guardDutyBucketConfirmation -eq 'y') { Write-Log -Message "Executing: aws guardduty update-publishing-destination --detector-id $detectorId --destination-id $currentS3Destinations.DestinationId --destination-properties DestinationArn=arn:aws:s3:::$bucketName,KmsKeyArn=$kmsArn | Out-Null" -LogFileName $LogFileName -Severity Verbose - aws guardduty update-publishing-destination --detector-id $detectorId --destination-id $currentS3Destinations.DestinationId --destination-properties DestinationArn=arn:aws:s3:::$bucketName,KmsKeyArn=$kmsArn | Out-Null + aws --region $Region guardduty update-publishing-destination --detector-id $detectorId --destination-id $currentS3Destinations.DestinationId --destination-properties DestinationArn=arn:aws:s3:::$bucketName,KmsKeyArn=$kmsArn | Out-Null } else { @@ -208,6 +222,48 @@ function Set-GuardDutyPublishDestinationBucket } } +function Enable-GuardDuty +{ + <# + .SYNOPSIS + Enables GuardDuty based on specified configuration + #> + + [String[]]$allRegionsArray = (aws ec2 describe-regions | ConvertFrom-Json)."Regions".RegionName + $regionConfirmation = Read-ValidatedHost 'Do you want enable guardduty for all regions? [y/n]' -ValidationType Confirm + if ($regionConfirmation -eq 'y') + { + for($i = 0; $i -lt $allRegionsArray.length; $i++) + { + Enable-GuardDuty-ForRegion -Region $allRegionsArray[$i] + Set-GuardDutyPublishDestinationBucket -Region $allRegionsArray[$i] + } + } + else + { + [String[]]$selectedRegionsArray = Read-ValidatedHost -Prompt "Please enter list of regions seperated by space" + $selectedRegionsArray = $selectedRegionsArray.Split(' ') | Select-Object -Unique + + for($i = 0; $i -lt $selectedRegionsArray.length; $i++) + { + if (-not($allRegionsArray -contains $selectedRegionsArray[$i])) + { + $notValidRegion = $selectedRegionsArray[$i] + $selectedRegionsArray = $selectedRegionsArray | ? {$_ -ne $notValidRegion} + Write-Log -Message "Region $notValidRegion doesn't exist" -LogFileName $LogFileName -LinePadding 2 + } + } + for($i = 0; $i -lt $selectedRegionsArray.length; $i++) + { + Enable-GuardDuty-ForRegion -Region $selectedRegionsArray[$i] + Set-GuardDutyPublishDestinationBucket -Region $selectedRegionsArray[$i] + } + } +} + + + + # *********** Main Flow *********** # Validate AWS configuration @@ -255,7 +311,7 @@ Update-S3Policy -RequiredPolicy $s3RequiredPolicy -CustomMessage $customMessage Enable-S3EventNotification -DefaultEventNotificationPrefix "AWSLogs/${callerAccount}/GuardDuty/" Enable-GuardDuty -Set-GuardDutyPublishDestinationBucket + # Output information needed to configure Sentinel data connector Write-RequiredConnectorDefinitionInfo -DestinationTable AWSGuardDuty \ No newline at end of file diff --git a/Detections/ASimDNS/imDNS_Miners.yaml b/Detections/ASimDNS/imDNS_Miners.yaml index ddab8fdd00..cd8c5db002 100644 --- a/Detections/ASimDNS/imDNS_Miners.yaml +++ b/Detections/ASimDNS/imDNS_Miners.yaml @@ -42,7 +42,7 @@ tactics: relevantTechniques: - T1496 tags: - - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/DnsEvents/DNS_Miners.yaml + - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/DnsEvents/DNS_Miners.yaml version: 1.0.0 - Schema: ASIMDns SchemaVersion: 0.1.1 diff --git a/Detections/ASimDNS/imDNS_TorProxies.yaml b/Detections/ASimDNS/imDNS_TorProxies.yaml index 9a6913b1cf..23ce0cca43 100644 --- a/Detections/ASimDNS/imDNS_TorProxies.yaml +++ b/Detections/ASimDNS/imDNS_TorProxies.yaml @@ -38,7 +38,7 @@ tactics: relevantTechniques: - T1048 tags: - - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/DnsEvents/DNS_TorProxies.yaml + - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/DnsEvents/DNS_TorProxies.yaml version: 1.0.0 - Schema: ASIMDns SchemaVersion: 0.1.1 diff --git a/Detections/ASimDNS/imDns_ExcessiveNXDOMAINDNSQueries.yaml b/Detections/ASimDNS/imDns_ExcessiveNXDOMAINDNSQueries.yaml index 3363fea491..dee7ee4eda 100644 --- a/Detections/ASimDNS/imDns_ExcessiveNXDOMAINDNSQueries.yaml +++ b/Detections/ASimDNS/imDns_ExcessiveNXDOMAINDNSQueries.yaml @@ -40,7 +40,7 @@ relevantTechniques: - T1568 - T1008 tags: - - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/InfobloxNIOS/ExcessiveNXDOMAINDNSQueries.yaml + - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/InfobloxNIOS/ExcessiveNXDOMAINDNSQueries.yaml version: 1.0.0 - Schema: ASIMDns SchemaVersion: 0.1.1 diff --git a/Detections/ASimDNS/imDns_HighNXDomainCount_detection.yaml b/Detections/ASimDNS/imDns_HighNXDomainCount_detection.yaml index 349df41820..4f401855b2 100644 --- a/Detections/ASimDNS/imDns_HighNXDomainCount_detection.yaml +++ b/Detections/ASimDNS/imDns_HighNXDomainCount_detection.yaml @@ -42,7 +42,7 @@ relevantTechniques: - T1568 - T1008 tags: - - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/DnsEvents/DNS_HighNXDomainCount_detection.yaml + - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/DnsEvents/DNS_HighNXDomainCount_detection.yaml version: 1.0.0 - Schema: ASIMDns SchemaVersion: 0.1.1 diff --git a/Detections/ASimDNS/imDns_IPEntity_DnsEvents.yaml b/Detections/ASimDNS/imDns_IPEntity_DnsEvents.yaml index 5ee7ab7aa2..bc72a3b881 100644 --- a/Detections/ASimDNS/imDns_IPEntity_DnsEvents.yaml +++ b/Detections/ASimDNS/imDns_IPEntity_DnsEvents.yaml @@ -43,7 +43,7 @@ triggerThreshold: 0 tactics: - Impact tags: - - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/ThreatIntelligenceIndicator/IPEntity_DnsEvents.yaml + - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/ThreatIntelligenceIndicator/IPEntity_DnsEvents.yaml version: 1.0.0 - Schema: ASIMDns SchemaVersion: 0.1.1 diff --git a/Detections/ASimNetworkSession/ExcessiveHTTPFailuresFromSource.yaml b/Detections/ASimNetworkSession/ExcessiveHTTPFailuresFromSource.yaml index 450045e796..5bd98b0d1a 100644 --- a/Detections/ASimNetworkSession/ExcessiveHTTPFailuresFromSource.yaml +++ b/Detections/ASimNetworkSession/ExcessiveHTTPFailuresFromSource.yaml @@ -5,7 +5,7 @@ description: | This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM NetworkSession schema' severity: Medium tags: - - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/SophosXGFirewall/ExcessiveAmountofDeniedConnectionsfromASingleSource.yaml + - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/SophosXGFirewall/ExcessiveAmountofDeniedConnectionsfromASingleSource.yaml version: 1.0.0 - Schema: ASimNetworkSessions SchemaVersion: 0.2.1 diff --git a/Detections/ASimWebSession/UnusualUAHackTool.yaml b/Detections/ASimWebSession/UnusualUAHackTool.yaml index e23d3e76ef..4d48b1a335 100644 --- a/Detections/ASimWebSession/UnusualUAHackTool.yaml +++ b/Detections/ASimWebSession/UnusualUAHackTool.yaml @@ -5,7 +5,7 @@ description: | This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM WebSession schema (ASIM WebSession Schema)' severity: Medium tags: - - ParentName: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/CiscoUmbrella/CiscoUmbrellaHackToolUserAgentDetected.yaml + - ParentName: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/CiscoUmbrella/CiscoUmbrellaHackToolUserAgentDetected.yaml version: 1.0.0 - Schema: ASimWebSession SchemaVersion: 0.2.1 diff --git a/Parsers/ASimDns/ARM/vimDnsVectraAI/vimDnsVectraAI.json b/Parsers/ASimDns/ARM/vimDnsVectraAI/vimDnsVectraAI.json index e750993f43..e7b6390eb2 100644 --- a/Parsers/ASimDns/ARM/vimDnsVectraAI/vimDnsVectraAI.json +++ b/Parsers/ASimDns/ARM/vimDnsVectraAI/vimDnsVectraAI.json @@ -26,7 +26,7 @@ { "type": "savedSearches", "apiVersion": "2020-08-01", - "name": "ASimDnsVectraAI", + "name": "vimDnsVectraAI", "dependsOn": [ "[concat('Microsoft.OperationalInsights/workspaces/', parameters('Workspace'))]" ], @@ -34,10 +34,10 @@ "etag": "*", "displayName": "DNS ASIM parser for Vectra AI Steams", "category": "ASIM", - "FunctionAlias": "ASimDnsVectraAI", + "FunctionAlias": "vimDnsVectraAI", "query": "let parser=\n(\n starttime:datetime=datetime(null), \n endtime:datetime=datetime(null),\n srcipaddr:string='*',\n domain_has_any:dynamic=dynamic([]),\n responsecodename:string='*', \n response_has_ipv4:string='*',\n response_has_any_prefix:dynamic=dynamic([]),\n eventtype:string='Query',\n disabled:bool=false\n) \n{\n let NetworkProtocolLookup = datatable(proto_d:real, NetworkProtocol:string)[\n 6, 'TCP',\n 17, 'UDP'];\n let DnsClassLookup = datatable(DnsQueryClass:int, DnsQueryClassName: string)[\n 0, 'Reserved',\n 1, 'IN',\n 2, 'Unassigned',\n 3, 'CH',\n 4, 'HS',\n 254, 'None',\n 255, 'Any'\n ];\n let HostnameRegex = @'^[a-zA-Z0-9-]{1,61}$';\n VectraStream_CL\n | where not(disabled)\n | where (isnull(starttime) or TimeGenerated >= starttime)\n and (isnull(endtime) or TimeGenerated <= endtime)\n | where metadata_type_s == 'metadata_dns'\n | where (srcipaddr == '*' or id_orig_h_s == srcipaddr)\n | where (array_length(domain_has_any) == 0 or query_s has_any(domain_has_any))\n | where (responsecodename == '*' or rcode_name_s =~ responsecodename)\n | where (response_has_ipv4 == '*' or has_ipv4(answers_s, response_has_ipv4))\n | where (array_length(response_has_any_prefix) == 0 or has_any_ipv4_prefix(answers_s, response_has_any_prefix))\n | where (eventtype == '*' or eventtype in~ ('Query', 'lookup'))\n | project-rename\n DvcDescription = hostname_s,\n DstDescription = resp_hostname_s,\n SrcDescription = orig_hostname_s,\n DnsFlagsAuthoritative = AA_b,\n DnsFlagsRecursionAvailable = RA_b,\n DnsFlagsRecursionDesired = RD_b,\n DnsFlagsTruncated = TC_b,\n DnsResponseName = answers_s,\n DnsQuery = query_s,\n DnsQueryTypeName = qtype_name_s,\n DstIpAddr = id_resp_h_s,\n DnsSessionId = community_id_s,\n SrcIpAddr = id_orig_h_s,\n DstDvcId = resp_huid_s,\n SrcDvcId = orig_huid_s,\n DvcId = sensor_uid_s,\n EventOriginalUid = uid_s\n | extend\n DstHostname = iff (DstDescription startswith \"IP-\" or not(DstDescription matches regex HostnameRegex), \"\", DstDescription),\n SrcHostname = iff (SrcDescription startswith \"IP-\" or not(SrcDescription matches regex HostnameRegex), \"\", SrcDescription),\n DvcHostname = iff (DvcDescription startswith \"IP-\" or not(DvcDescription matches regex HostnameRegex), \"\", DvcDescription),\n NetworkProtocolVersion = toupper(id_ip_ver_s),\n DnsResponseCode = toint(rcode_d),\n DnsResponseCodeName = toupper(rcode_name_s),\n DnsQueryClass = toint(qclass_d),\n DnsQueryType = toint(qtype_d),\n DstPortNumber = toint(id_resp_p_d),\n EventCount = toint(1),\n EventEndTime = unixtime_milliseconds_todatetime(ts_d),\n EventOriginalSubType = split(metadata_type_s, '_')[1],\n EventProduct = 'Vectra Stream',\n EventResult = case(tolong(rcode_d) > 0, \"Failure\", \"Success\"),\n EventSchema = 'Dns', \n EventSchemaVersion='0.1.3',\n EventType = 'Query',\n EventVendor = 'Vectra AI',\n SrcDvcIdType = 'VectraId',\n DstDvcIdType = 'VectraId',\n DvcIdType = 'VectraId',\n SrcPortNumber = toint(id_orig_p_d),\n TransactionIdHex = tostring(toint(trans_id_d)),\n EventSubType = iff (saw_reply_b, \"response\", \"request\")\n | lookup DnsClassLookup on DnsQueryClass\n | lookup NetworkProtocolLookup on proto_d\n | extend\n EventResultDetails = DnsResponseCodeName,\n EventStartTime = EventEndTime,\n SessionId = DnsSessionId,\n Domain = DnsQuery,\n Hostname = DstHostname,\n IpAddr = SrcIpAddr,\n Dvc = coalesce (DvcId, DvcDescription),\n Src = SrcIpAddr,\n Dst = DstIpAddr\n | project-away\n *_d, *_s, *_b, *_g\n };\nparser(starttime, endtime, srcipaddr, domain_has_any, responsecodename, response_has_ipv4, response_has_any_prefix, eventtype, disabled)", "version": 1, - "functionParameters": "disabled:bool=False" + "functionParameters": "starttime:datetime=datetime(null), endtime:datetime=datetime(null), srcipaddr:string='*', domain_has_any:dynamic=dynamic([]), responsecodename:string='*', response_has_ipv4:string='*', response_has_any_prefix:dynamic=dynamic([]), eventtype:string='Query', disabled:bool=False" } } ] diff --git a/Parsers/ASimDns/Parsers/vimDnsVectraAI.yaml b/Parsers/ASimDns/Parsers/vimDnsVectraAI.yaml index 3c38b0a4cf..c240fe8457 100644 --- a/Parsers/ASimDns/Parsers/vimDnsVectraAI.yaml +++ b/Parsers/ASimDns/Parsers/vimDnsVectraAI.yaml @@ -14,9 +14,33 @@ References: Link: https://aka.ms/AboutASIM Description: | This ASIM parser supports normalizing Vectra AI Steams logs to the ASIM DNS normalized schema. -ParserName: ASimDnsVectraAI -EquivalentBuiltInParser: _ASim_Dns_VectraAI +ParserName: vimDnsVectraAI +EquivalentBuiltInParser: _Im_Dns_VectraAI ParserParams: + - Name: starttime + Type: datetime + Default: datetime(null) + - Name: endtime + Type: datetime + Default: datetime(null) + - Name: srcipaddr + Type: string + Default: '*' + - Name: domain_has_any + Type: dynamic + Default: dynamic([]) + - Name: responsecodename + Type: string + Default: '*' + - Name: response_has_ipv4 + Type: string + Default: '*' + - Name: response_has_any_prefix + Type: dynamic + Default: dynamic([]) + - Name: eventtype + Type: string + Default: 'Query' - Name: disabled Type: bool Default: false diff --git a/Solutions/SAP/sapcon-instance-update.sh b/Solutions/SAP/sapcon-instance-update.sh index 53d6b8fcb8..7dd06a6b2e 100755 --- a/Solutions/SAP/sapcon-instance-update.sh +++ b/Solutions/SAP/sapcon-instance-update.sh @@ -1,4 +1,88 @@ #!/bin/bash + +function pause() { + if [ ! "$CONFIRMALL" ]; then + read -r -p "$*" + fi +} + +function check_package() { + if ! which "$1" >/dev/null 2>&1; then + echo "Binary $1 not found" + echo "Please install $1 and run the upgrade script again" + exit 1 + fi +} + +#global +dockerimage=mcr.microsoft.com/azure-sentinel/solutions/sapcon +sdkfileloc=/sapcon-app/inst/ +CONTAINERNAMES=() + +while [[ $# -gt 0 ]]; do + case $1 in + --confirm-all-prompts) + CONFIRMALL=1 + shift 1 + ;; + --no-testrun) + NOTESTRUN=1 + shift 1 + ;; + --sdk) + SDKFILELOC="$2" + SDKFILELOC="${SDKFILELOC/#\~/$HOME}" + shift 2 + ;; + --containername) + CONTAINERNAMES+=("$2") + shift 2 + ;; + --devmode) + DEVMODE=1 + shift 1 + ;; + --dev-acr) + DEVURL="$2" + shift 2 + ;; + --dev-acr-login) + DEVACRLOGIN="$2" + shift 2 + ;; + --dev-acr-pwd) + DEVACRPWD="$2" + shift 2 + ;; + --preview) + PREVIEW=1 + shift 1 + ;; + --force) + FORCE=1 + shift 1 + ;; + --script-debug) + set -x + shift 1 + ;; + -*) + echo "Unknown option $1" + echo "Valid options are" + echo "--confirm-all-prompts" + echo "--preview" + echo "--script-debug" + echo "--no-testrun" + echo "--sdk " + echo "--containername [--containername ]..." + exit 1 + ;; + *) + POSITIONAL_ARGS+=("$1") # save positional arg + shift # past argument + ;; + esac +done #Copyright (c) Microsoft Corporation. All rights reserved. echo 'Microsoft Azure Sentinel SAP Continuous Threat Monitoring. SAP ABAP Logs Connector - Preview @@ -7,88 +91,178 @@ Copyright (c) Microsoft Corporation. You may use this preview software internally and only in accordance with the Azure preview terms, located at https://azure.microsoft.com/support/legal/preview-supplemental-terms/ Microsoft reserves all other rights -****' -function pause(){ - read -p "$*" -} +**** - -#global -dockerimage=mcr.microsoft.com/azure-sentinel/solutions/sapcon -tagver=":latest-preview" -olddockerimage=sentinel4sapprivateprview.azurecr.io/sapcon -containername=sapcon -sysconf=systemconfig.ini -acr=sentinel4sapprivateprview.azurecr.io -sdkfileloc=/sapcon-app/inst/ - -echo ' -----Update All MS SAPcon instances---- This process will download the latest version of Sentinel SAP Connector, Updates current image and containers. A currently running version of the instance will be stopped and automatically start after the process. In order to process you will need the following prerequisites: ' +# Parameter validation +if [ -n "$SDKFILELOC" ] && [ ! -f "$SDKFILELOC" ]; then + echo 'Invalid SDK path' + exit 1 +fi +# Image selection +if [ $DEVMODE ]; then + dockerimage=$(echo "$DEVURL" | awk -F: '{print $1}') + acr=$(echo "$DEVURL" | awk -F/ '{print $1}') + sudo docker login "$acr" -u "$DEVACRLOGIN" -p "$DEVACRPWD" + tagver=$(echo "$DEVURL" | awk -F: '{print ":"$2}') +else + dockerimage=mcr.microsoft.com/azure-sentinel/solutions/sapcon + if [ $PREVIEW ]; then + tagver=":latest-preview" + else + tagver=":latest" + fi +fi + +check_package docker +check_package jq echo 'Starting Docker image Pull' docker pull $dockerimage$tagver -if [ $? -eq 1 ]; -then +if [ $? -eq 1 ]; then echo 'There is an error with the docker image - please Check network connection' exit 1 fi pause ' Image has been downloaded - Press key to continue with the Update' +repoimageid=$(docker inspect "$dockerimage$tagver" --format '{{.Id}}') contlist=$(docker container ls -a | awk 'NR!=1 {print $1}') +while IFS= read -r contid; do + containerlabel=$(docker inspect "$contid" | jq '.[].Config.Labels."com.visualstudio.msazure.image.build.repository.name"') + if [ "$containerlabel" == '"ASI-Sentinel4SAP"' ]; then + contimg=$(docker inspect --format='{{.Image}}' "$contid") + contname=$(docker inspect --format '{{.Name}}' "$contid") + contname="${contname:1}" + if [[ -z ${CONTAINERNAMES[*]} ]] || [[ ${CONTAINERNAMES[*]} =~ $contname ]]; then + echo "Checking if upgrade is necessary for container $contname" + if [ ! "$contimg" = "$repoimageid" ] || [ $FORCE = 1 ]; then + echo "Updating $contname" + if [ -n "$contid" ]; then + sysfileloc=$(docker inspect -f '{{ .Mounts }}' $contname | awk 'NR==1 {print $2}') + if [ -z "$sysfileloc" ]; then + echo "Container $contname cannot be updated - The mount point is empty" + exit 1 + fi + last=${sysfileloc: -1} -while IFS= read -r contid -do - contimg=$(docker inspect --format='{{.Config.Image}}' $contid) - contname=$(docker ps -a --filter id=$contid --format '{{.Names}}') - - if [[ "$contimg" = *"$dockerimage"* ]] || [[ "$contimg" = *"$olddockerimage"* ]] - then - echo ' ' - echo Updating $contname... - if [ ! -z $contid ] - then - sysfileloc=$(docker inspect -f '{{ .Mounts }}' $contname | awk 'NR==1 {print $2}') - if [ ! -z $sysfileloc ] - then - last=${sysfileloc: -1} + if [ "$last" != "/" ]; then + sysfileloc="$sysfileloc/" + fi - if [ "$last" != "/" ]; - then - sysfileloc="$sysfileloc/" + read -r -a containervariables <<<"$(docker inspect $contname -f '{{.Config.Env}}' | tr -d '[' | tr -d ']' | tr ' ' ' ')" + envstring="" + for variable in "${containervariables[@]}"; do + if [[ ! $variable == PATH=* ]] && + [[ ! $variable == LANG=* ]] && + [[ ! $variable == GPG_KEY=* ]] && + [[ ! $variable == PYTHON_VERSION=* ]] && + [[ ! $variable == PYTHON_PIP_VERSION=* ]] && + [[ ! $variable == PYTHON_SETUPTOOLS_VERSION=* ]] && + [[ ! $variable == PYTHON_GET_PIP_URL=* ]] && + [[ ! $variable == PYTHON_GET_PIP_SHA256=* ]]; then + envstring+="-e $variable " + fi + done + + isRunning=$(docker inspect --format='{{.State.Running}}' "$contname") + if [ "$isRunning" == "true" ]; then + docker stop "$contname" + fi + mkdir -p /tmp/sapcon-update/ >/dev/null 2>&1 + sudo rm -rf "/tmp/sapcon-update/$contname" >/dev/null 2>&1 + mkdir "/tmp/sapcon-update/$contname" >/dev/null 2>&1 + + #renaming the container, creating a new test container + oldname="$contname-OLD" + docker container rename "$contname" "$oldname" >/dev/null + + #Extract SDK from old container, or use a newly supplied one + if [ -n "$SDKFILELOC" ]; then + mkdir -p "/tmp/sapcon-update/$contname/inst" + cp "$SDKFILELOC" "/tmp/sapcon-update/$contname/inst/" + else + docker cp "$oldname":$sdkfileloc "/tmp/sapcon-update/$contname" + fi + sdkfilename=$(ls -1r /tmp/sapcon-update/$contname/inst/nwrfc*.zip | head -n 1) + + if [ ! $NOTESTRUN ]; then + # If test run is required + docker create -v "$sysfileloc:/sapcon-app/sapcon/config/system" $envstring --name "$contname" $dockerimage$tagver --sapconinstanceupdate >/dev/null + + docker cp "$sdkfilename" "$contname":$sdkfileloc + docker start "$contname" >/dev/null + + let timeelapsed=0 + dryruninprogress="true" + echo -n "Starting container test run..." + while [ "$dryruninprogress" == "true" ] && [ $timeelapsed -le 120 ]; do + dryruninprogress=$(docker inspect --format='{{.State.Running}}' "$contname") + if [ "$dryruninprogress" == "false" ]; then + containerexitcode=$(docker container inspect --format '{{.State.ExitCode}}' "$contname") + printf "\nContainer dry run exited. Exit code $containerexitcode" + if [ "$containerexitcode" == 0 ]; then + dryrunsuccess=1 + docker rm "$contname" >/dev/null + docker create -v "$sysfileloc:/sapcon-app/sapcon/config/system" $envstring --name "$contname" $dockerimage$tagver >/dev/null + docker cp $sdkfilename "$contname":"$sdkfileloc" + elif [ "$containerexitcode" == 7 ]; then + printf "\nInsufficient authorizations in SAP" + dryrunsuccess=0 + break + elif [ "$containerexitcode" == 8 ]; then + printf "\nContainer runtime error" + dryrunsuccess=0 + break + else + printf "\nContainer exited with code $containerexitcode" + dryrunsuccess=0 + break + fi + fi + sleep 1 + let timeelapsed=timeelapsed+1 + echo -n "." + done + if [ "$dryruninprogress" == "true" ]; then + # container did not exit after 60 seconds + printf "\nContainer is running after timeout period expired" + docker stop "$contname" >/dev/null + fi + + if [ "$dryrunsuccess" == 1 ]; then + printf "\nTest run successful, removing old container" + docker rm "$oldname" >/dev/null + else + printf "\nTest run NOT successful, removing new container, renaming the old container to original name" + echo "----Container debug logs START----" + docker logs "$contname" + echo "----Container debug logs END----" + docker rm "$contname" >/dev/null + docker rename "$oldname" "$contname" >/dev/null + fi + else + docker create -v "$sysfileloc:/sapcon-app/sapcon/config/system" $envstring --name "$contname" $dockerimage$tagver >/dev/null + docker cp "$sdkfilename" "$contname":"$sdkfileloc" + docker rm "$oldname" + fi + sudo rm -rf /tmp/sapcon-update >/dev/null 2>&1 fi - - contstate=$(docker inspect --format='{{.State.Running}}' $contname ) - - # pause 'press enter' - if [ $contstate == "false" ] - then - docker cp $contname:$sdkfileloc $(pwd) - docker container rm $contname >/dev/null - docker create -v $sysfileloc:/sapcon-app/sapcon/config/system --name $contname $dockerimage$tagver >/dev/null - docker cp "$(pwd)/inst/" $contname:/sapcon-app/ >/dev/null - echo 'Container "'"$contname"'" was updated - please start the app by running "docker start '"$contname"'"' - echo '' - else - docker cp $contname:$sdkfileloc $(pwd) - docker stop $contname >/dev/null - docker container rm $contname >/dev/null - docker create -v $sysfileloc:/sapcon-app/sapcon/config/system --name $contname $dockerimage$tagver >/dev/null - docker cp "$(pwd)/inst/" $contname:/sapcon-app/ >/dev/null - docker start $contname >/dev/null - echo 'Container "'"$contname"'" was updated' - echo '' + if [ "$isRunning" == "true" ]; then + echo "Starting container $contname" + docker start "$contname" >/dev/null fi else - echo 'Container "'"$contname"'" cannot be updated - The mount point is empty' - echo ' ' + echo "Container image for container $contname is identical to the one in the repo" fi else - echo '' + echo "Skipping container $contname as it is not specified in --containername list" fi - - fi -done <<< "$contlist" + else + echo "Skipping container id $contid as it does not appear to be a sapcon container" + fi +done \ + <<<"$contlist" diff --git a/Solutions/SAP/sapcon-sentinel-kickstart.sh b/Solutions/SAP/sapcon-sentinel-kickstart.sh index a63326928b..5729b49df8 100755 --- a/Solutions/SAP/sapcon-sentinel-kickstart.sh +++ b/Solutions/SAP/sapcon-sentinel-kickstart.sh @@ -1,20 +1,377 @@ #!/bin/bash -# if [ "$EUID" -ne 0 ] -# then echo "Please run as root" -# exit -# fi +function verlte() { + [ "$1" = "$(echo -e "$1\n$2" | sort -V | head -n1)" ] +} +function verlt() { + [ "$1" = "$2" ] && return 1 || verlte $1 $2 +} + +function read_password() { + varname="$1" + while [ -z "${!varname}" ]; do + echo -n "Enter value for $2: " >$(tty) + unset CHARCOUNT + stty -echo + CHARCOUNT=0 + unset PASSWORD + unset CHAR + unset PROMPT + while IFS= read -p "$PROMPT" -r -s -n 1 CHAR; do + # Enter - accept password + if [[ $CHAR == $'\0' ]]; then + break + fi + # Backspace + if [[ $CHAR == $'\177' ]]; then + if [ $CHARCOUNT -gt 0 ]; then + CHARCOUNT=$((CHARCOUNT - 1)) + PROMPT=$'\b \b' + PASSWORD="${PASSWORD%?}" + else + PROMPT='' + fi + else + CHARCOUNT=$((CHARCOUNT + 1)) + PROMPT='*' + PASSWORD+="$CHAR" + fi + done + stty echo + echo "" + eval "$1"='$PASSWORD' + if [ -z "${!varname}" ]; then + echo "Invalid value supplied for $1. Value cannot be empty. Please try again" >$(tty) + fi + done +} + +function read_value() { + varname="$1" + while [ -z "${!varname}" ]; do + read -r -p "Enter $2: " varvalue + if [ -z "$varvalue" ]; then + echo "Supplied value for $2 is empty. Please try again." >$(tty) + fi + eval "$1"='$varvalue' + done +} + +function pause() { + if [ ! "$CONFIRMALL" ]; then + read -r -p "$*" + fi +} + +function install_package() { + # $1 package name + # $2 install command + if ! which "$1" >/dev/null 2>&1; then + echo "Installing $1" + if ! cmdresult=$(sudo $2 $1 2>&1); then + echo "Failed to install $1" + echo "$cmdresult" + exit 1 + fi + fi +} + +# MODE is one of +# kvmi - Key Vault - Managed Identity +# kvsi - Key Vault - Supplied Identity +# cfgf - Config File + +# CONNECTIONMODE is one of +# abap +# mserv + +MODE="kvmi" +CONNECTIONMODE="abap" +CONFIGPATH="/opt" +TRUSTEDCA=() + +while [[ $# -gt 0 ]]; do + case $1 in + --keymode) + MODE="$2" + shift 2 + ;; + --configpath) + CONFIGPATH="$2" + shift 2 + ;; + --connectionmode) + CONNECTIONMODE="$2" + shift 2 + ;; + --abapserver) + ABAPSERVER="$2" + shift 2 + ;; + --systemnr) + SYSTEMNR="$2" + shift 2 + ;; + --sid) + SID="$2" + shift 2 + ;; + --clientnumber) + CLIENTNUMBER="$2" + shift 2 + ;; + --messageserverhost) + MESSAGESERVERHOST="$2" + shift 2 + ;; + --messageserverport) + MESSAGESERVERPORT="$2" + shift 2 + ;; + --logongroup) + LOGONGROUP="$2" + shift 2 + ;; + --sapusername) + uservar="$2" + shift 2 + ;; + --sappassword) + passvar="$2" + shift 2 + ;; + --sdk) + SDKFILELOC="$2" + SDKFILELOC="${SDKFILELOC/#\~/$HOME}" + shift 2 + ;; + --appid) + APPID="$2" + shift 2 + ;; + --appsecret) + APPSECRET="$2" + shift 2 + ;; + --tenantid) + TENANT="$2" + shift 2 + ;; + --kvaultname) + kv="$2" + shift 2 + ;; + --loganalyticswsid) + logwsid="$2" + shift 2 + ;; + --loganalyticskey) + logpubkey="$2" + shift 2 + ;; + --use-snc) + USESNC=1 + shift + ;; + --cryptolib) + SAPCRYPTOLIB="$2" + SAPCRYPTOLIB="${SAPCRYPTOLIB/#\~/$HOME}" + shift 2 + ;; + --sapgenpse) + SAPGENPSE="$2" + SAPGENPSE="${SAPGENPSE/#\~/$HOME}" + shift 2 + ;; + --client-cert) + CLIENTCERT="$2" + CLIENTCERT="${CLIENTCERT/#\~/$HOME}" + shift 2 + ;; + --client-key) + CLIENTKEY="$2" + CLIENTKEY="${CLIENTKEY/#\~/$HOME}" + shift 2 + ;; + --cacert) + ca="$2" + ca="${ca/#\~/$HOME}" + TRUSTEDCA+=("$ca") + shift 2 + ;; + --client-pfx) + CLIENTPFX="$2" + CLIENTPFX="${CLIENTPFX/#\~/$HOME}" + shift 2 + ;; + --client-pfx-passwd) + CLIENTPFXPWD="$2" + CLIENTPFXPWD="${CLIENTPFXPWD/#\~/$HOME}" + shift 2 + ;; + --server-cert) + SERVERCERT="$2" + SERVERCERT="${SERVERCERT/#\~/$HOME}" + shift 2 + ;; + --http-proxy) + HTTPPROXY="$2" + ;; + --confirm-all-prompts) + CONFIRMALL=1 + shift 1 + ;; + --devmode) + DEVMODE=1 + shift 1 + ;; + --dev-acr) + DEVURL="$2" + shift 2 + ;; + --dev-acr-login) + DEVACRLOGIN="$2" + shift 2 + ;; + --dev-acr-pwd) + DEVACRPWD="$2" + shift 2 + ;; + --preview) + PREVIEW=1 + shift 1 + ;; + --script-debug) + set -x + shift 1 + ;; + -*) + echo "Unknown option $1" + echo "Valid options are" + echo "--keymode [kvmi|kvsi|cfgf]" + echo "--connectionmode [abap|mserv]" + echo "--configpath " + echo "--apabserver " + echo "--systemnr " + echo "--sid " + echo "--clientnumber " + echo "--messageserverhost " + echo "--messageserverport " + echo "--logongroup " + echo "--sapusername " + echo "--sappassword " + echo "--sdk " + echo "--appid " + echo "--appsecret " + echo "--tenantid " + echo "--kvaultname " + echo "--loganalyticswsid " + echo "--loganalyticskey " + echo "--use-snc" + echo "--cryptolib " + echo "--sapgenpse " + echo "--client-cert " + echo "--client-key " + echo "--cacert --cacert ..." + echo "--client-pfx " + echo "--client-pfx-passwd " + echo "--server-cert " + echo "--http-proxy " + echo "--confirm-all-prompts" + echo "--preview" + exit 1 + ;; + *) + POSITIONAL_ARGS+=("$1") # save positional arg + shift # past argument + ;; + esac +done +# Parameter set validation +if [ "$MODE" != 'kvsi' ] && [ "$MODE" != 'kvmi' ] && [ "$MODE" != 'cfgf' ]; then + echo 'Invalid setting for --keymode. Supported values are "kvsi", "kvmi" or "cfgf"' + exit 1 +fi + +if [ "$CONNECTIONMODE" != 'abap' ] && [ "$CONNECTIONMODE" != 'mserv' ]; then + echo 'Invalid setting for --connectionmode. Supported values are "abap", "mserv"' + exit 1 +fi + +if [ "$MODE" == 'kvsi' ] && { [ -z "$APPID" ] || [ -z "$APPSECRET" ] || [ -z "$TENANT" ] || [ -z "$kv" ]; }; then + printf 'Missing parameter values. -m kvsi requires --appid, --appsecret, --tenantid, --kvaultname parameters.\nProvide values interactively now or rerun the script with relevant switches.' + read_value APPID "Application ID" + read_value APPSECRET "Application Secret" + read_value TENANT "Tenant ID" + read_value kv "Keyvault Name" +fi + +if [ $USESNC ] && { [ -z "$SAPCRYPTOLIB" ] || [ -z "$SAPGENPSE" ] || [ -z "$SERVERCERT" ] || { { [ -z "$CLIENTKEY" ] || [ -z "$CLIENTCERT" ]; } && [ -z "$CLIENTPFX" ]; }; }; then + echo 'Invalid parameters -e requires --cryptolib, --sapgenpse, --server-cert, --client-cert, --client-key, or --client-pfx parameters' + exit 1 +elif [ ! $USESNC ] && { [ -n "$SAPCRYPTOLIB" ] || [ -n "$SAPGENPSE" ] || [ -n "$CLIENTCERT" ] || [ -n "$SERVERCERT" ] || [ -n "$CLIENTKEY" ] || [ -n "$CLIENTPFX" ] || [ -n "$CLIENTPFXPWD" ] || [ -n "${TRUSTEDCA[0]}" ]; }; then + echo 'Invalid parameters. If using --cryptolib, --sapgenpse, --client-cert, --client-key , --client-pfx, --server-cert parameters, --cacert, specify --use-snc' + exit 1 +fi + +if [ -n "$ABAPSERVER" ] && { [ -n "$MESSAGESERVERHOST" ] || [ -n "$MESSAGESERVERPORT" ] || [ -n "$LOGONGROUP" ]; }; then + echo 'Invalid parameters. --abapserver cannot be used in conjunction with --messageserverhost, --messageserverport or --logongroup' + exit 1 +fi + +if [ $USESNC ] && [ ! -f "$SAPCRYPTOLIB" ]; then + echo 'Invalid SAP Crypto lib path' + exit 1 +fi + +if [ $USESNC ] && [ ! -f "$SAPGENPSE" ]; then + echo 'Invalid sapgenpse path' + exit 1 +fi + +if [ $USESNC ] && [ -n "$CLIENTCERT" ] && [ ! -f "$CLIENTCERT" ]; then + echo 'Invalid client certificate path' + exit 1 +fi + +if [ $USESNC ] && [ -n "$CLIENTKEY" ] && [ ! -f "$CLIENTKEY" ]; then + echo 'Invalid client pfx path' + exit 1 +fi + +if [ $USESNC ] && [ -n "$CLIENTPFX" ] && [ ! -f "$CLIENTPFX" ]; then + echo 'Invalid client key path' + exit 1 +fi + +if [ $USESNC ] && [ ! -f "$SERVERCERT" ]; then + echo 'Invalid server certificate path' + exit 1 +fi + +if [ $USESNC ] && [ -n "${TRUSTEDCA[0]}" ]; then + for i in "${TRUSTEDCA[@]}"; do + : + if [ ! -f "$i" ]; then + echo 'Invalid ca file path' + exit 1 + fi + done +fi + +if [ -n "$SDKFILELOC" ] && [ ! -f "$SDKFILELOC" ]; then + echo 'Invalid SDK path' + exit 1 +fi + +# End of parameter validation echo ' - ************************************************************ - THIS INSTALLATION SCRIPT WILL USE ROOT ACCESS TO: -1. INSTALL AND EXTRACT DOCKER IMAGE - +1. DOWNLOAD, INSTALL AND CONFIGURE DOCKER IMAGE 2. ADD THE CURRENT USER TO THE DOCKER GROUP - 3. RUN THE CONNECTOR AS A DOCKER CONTAINER ON THE HOST ************************************************************* @@ -23,20 +380,12 @@ The Azure Sentinel SAP solution is currently in PREVIEW. The Azure Preview Supplemental Terms include additional legal terms that apply to Azure features that are in beta, preview, or otherwise not yet released into general availability. For more information, see https://azure.microsoft.com/support/legal/preview-supplemental-terms/. -****' +**** -function pause(){ - read -p "$*" -} - -echo ' ------Sapcon on Azure – ABAP only KickStart---- +-----Microsoft continuous threat monitoring for SAP KickStart script---- In order to complete the installation process, you need: -- Your SAP Continuous Threat Monitoring container registry password. -The access and password must be granted explicitly to you by Microsoft, is personal and may not be shared. - - SAP version: The Azure Sentinel SAP Logs connector requires a SAP version of 7.4 or higher. - SAP system details: Make a note of your SAP system IP address, system number, system ID, and client for use during the installation. @@ -44,9 +393,9 @@ The access and password must be granted explicitly to you by Microsoft, is perso - SAP change requests: Import any required change requests for your logs from the CR folder of this repository - https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/SAP/CR. Configure the following SAP Log change requests to enable support for ingesting specific SAP logs into Azure Sentinel. -- SAP Basis versions 7.5 and higher: install NPLK900144 -- SAP Basis version 7.4: install NPLK900146 -- To create your SAP role in any SAP version: install NPLK900140 +- SAP Basis versions 7.5 and higher: install NPLK900180 +- SAP Basis version 7.4: install NPLK900179 +- To create your SAP role in any SAP version: install NPLK900163 Tip: To create your SAP role with all required authorizations, deploy the SAP change request NPLK900140 on your SAP system. This change request creates the /msftsen/sentinel_connector role, and assigns the role to the ABAP connecting to Azure Sentinel. @@ -63,307 +412,443 @@ For more information see the SAP documentation. pause '[Press enter to agree and proceed as we guide you through the installation process. Alternately, press CTRL+C to cancel the process]' - #Globals -dockerimage=mcr.microsoft.com/azure-sentinel/solutions/sapcon containername=sapcon sysconf=systemconfig.ini -tagver=":latest-preview" -logwsid=LOGWSID -logwspubkey=LOGWSPUBLICKEY -abapuser=ABAPUSER -abappass=ABAPPASS -os=$(cat /etc/os-release | awk 'BEGIN { FS="=" } $1=="ID" {print $2}') -ver_id=$(cat /etc/os-release | awk 'BEGIN { FS="=" } $1=="VERSION_ID" {print $2}' | awk '{print substr($0, 2, length($0) - 2) }') -id_like=$(cat /etc/os-release | awk 'BEGIN { FS="=" } $1=="ID_LIKE" {print $2}') +os=$(awk /dev/null - sudo apt-get install -y -qq jq docker.io unzip >/dev/null - curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash >/dev/null 2>&1 + install_package "jq" "apt install" + install_package "unzip" "apt install -y -qq" + sudo apt install -y -qq docker.io >/dev/null + echo "Installing docker" + if [ "$MODE" != "cfgf" ]; then + echo "Installing Azure CLI" + curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash >/dev/null 2>&1 + fi -elif [ $os == '"rhel"' ] -then +elif [ "$os" == '"rhel"' ]; then #RHEL + echo 'Updating package lists' sudo yum update -y --disablerepo='*' --enablerepo='*microsoft*' >/dev/null - sudo yum install -y nc >/dev/null - sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc >/dev/null - echo -e "[azure-cli] -name=Azure CLI -baseurl=https://packages.microsoft.com/yumrepos/azure-cli -enabled=1 -gpgcheck=1 -gpgkey=https://packages.microsoft.com/keys/microsoft.asc" | sudo tee /etc/yum.repos.d/azure-cli.repo >/dev/null - sudo yum install azure-cli -y >/dev/null + install_package "nc" "yum install -y" + install_package "jq" "yum install -y" + + if [ "$MODE" != "cfgf" ]; then + sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc >/dev/null + echo -e "[azure-cli]\nname=Azure CLI\nbaseurl=https://packages.microsoft.com/yumrepos/azure-cli\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" | sudo tee /etc/yum.repos.d/azure-cli.repo >/dev/null + echo "Installing Azure CLI" + sudo yum install azure-cli -y >/dev/null + fi sudo yum install -y yum-utils >/dev/null sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >/dev/null + echo "Installing Docker" sudo yum install docker-ce docker-ce-cli containerd.io -y >/dev/null sudo systemctl enable docker.service sudo systemctl start docker.service -elif [ $os == '"sles"' ] -then +elif [ "$os" == '"sles"' ]; then # SUSE + echo "Updating package lists" + sudo zypper refresh >/dev/null + echo "Updating installed packages" sudo zypper update -y >/dev/null - sudo zypper install -y curl >/dev/null - sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc >/dev/null - sudo zypper addrepo --name 'Azure CLI' --check https://packages.microsoft.com/yumrepos/azure-cli azure-cli >/dev/null - sudo zypper install -y --from azure-cli azure-cli >/dev/null - sudo zypper install -y docker >/dev/null - sudo systemctl enable docker.service - sudo systemctl start docker.service + install_package "curl" "zypper install -y" + install_package "jq" "zypper install -y" + install_package "docker" "zypper install -y" + sudo systemctl enable docker.service + sudo systemctl start docker.service + if [ "$MODE" != "cfgf" ]; then + if ! rpm -qa | grep gpg-pubkey-be1229cf-5631588c >/dev/null; then + sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc >/dev/null + echo "Adding Microsoft GPG key" + fi + if ! sudo zypper lr | grep "Azure CLI" >/dev/null; then + sudo zypper addrepo --name 'Azure CLI' --check https://packages.microsoft.com/yumrepos/azure-cli azure-cli >/dev/null + echo "Adding Microsoft Azure CLI repository" + fi + if which az >/dev/null 2>&1; then + #AZ is installed, check if it is out-of date version with compatibility issues + azver=$(az version | jq '."azure-cli"') + if verlte "2.33.1" "$azver"; then + echo "Installed version $azver is out of date, removing older version" + sudo zypper rm -y --clean-deps azure-cli >/dev/null + echo "Installing Azure CLI" + sudo zypper install -y --from azure-cli azure-cli >/dev/null + fi + else + echo "Installing Azure CLI" + sudo zypper install -y --from azure-cli azure-cli >/dev/null + fi + fi else - echo VM version is not sufficient. Create one of the following VM OS images: Ubuntu version 18.04 or higher, SLES version 15 or higher, or RHEL version 7.7 or higher + echo OS version is not suppored. Supported OS: Ubuntu version 18.04 or higher, SLES version 15 or higher, or RHEL version 7.7 or higher exit 1 fi +if [ $DEVMODE ]; then + dockerimage=$(echo "$DEVURL" | awk -F: '{print $1}') + acr=$(echo "$DEVURL" | awk -F/ '{print $1}') + sudo docker login "$acr" -u "$DEVACRLOGIN" -p "$DEVACRPWD" + tagver=$(echo "$DEVURL" | awk -F: '{print ":"$2}') +else + dockerimage=mcr.microsoft.com/azure-sentinel/solutions/sapcon + if [ $PREVIEW ]; then + tagver=":latest-preview" + else + tagver=":latest" + fi +fi # sudo groupadd docker -sudo usermod -aG docker $USER -az login --identity --allow-no-subscriptions >/dev/null 2>&1 -if [ ! $? -eq 0 ] -then - echo 'VM is not set with managed identity or the AZ client was not installed correctly. -Set and grant relevant Key Vault permissions and make sure that Azure CLI is installed by running "az login", for more information check - https://docs.microsoft.com/cli/azure/install-azure-cli .' - exit 1 -fi +echo "Creating group 'docker' and adding current user to 'docker' group" +sudo usermod -aG docker "$USER" -echo ' -VM is ready to deploy the Azure Sentinel SAP data connector. All OS dependencies are met. -' +if { [ "$MODE" == 'kvmi' ] && [ -z "$kv" ]; } || { [ "$MODE" == 'kvsi' ] && [ -z "$kv" ]; }; then + read_value kv "KeyVault Name" +fi + +if [ "$MODE" == "kvmi" ]; then + echo "Validating Azure managed identity" + az login --identity --allow-no-subscriptions >/dev/null 2>&1 + if [ ! $? -eq 0 ]; then + printf 'VM is not set with managed identity or the AZ client was not installed correctly.\nSet and grant relevant Key Vault permissions and make sure that Azure CLI is installed by running "az login"\nFor more information check - https://docs.microsoft.com/cli/azure/install-azure-cli' + exit 1 + fi +elif [ "$MODE" == "kvsi" ]; then + echo "Validating service principal identity" + az login --service-principal -u "$APPID" -p "$APPSECRET" --tenant "$TENANT" --allow-no-subscriptions >/dev/null 2>&1 + if [ ! $? -eq 0 ]; then + echo "Logon with $APPID failed, please check application ID, secret and tenant ID. Ensure the application has been added as an enterprise application" + exit 1 + fi + az keyvault secret list --id "https://$kv.vault.azure.net/" >/dev/null 2>&1 + if [ ! $? -eq 0 ]; then + echo "Cannot connect to keyvault $kv. Make sure application $APPID has been granted privileges to the keyvault" + exit 1 + fi +fi + +echo 'Deploying Azure Sentinel SAP data connector.' echo 'Starting Docker image pull' + sudo docker pull $dockerimage$tagver -if [ $? -eq 1 ]; -then +if [ $? -eq 1 ]; then echo 'Error downloading the Azure Sentinel SAP data connector.' exit 1 fi -pause 'Latest Azure Sentinel data connector downloaded successfully. Press ENTER to continue. -' -echo 'Enter the following information about your SAP instance: -' -read -p 'Hostname: ' hostvar -read -p 'System Number: ' sysnrvar -read -p 'SID : ' sysid -while [ ${#sysid} -ne 3 ] -do - echo 'Invalid SID - try again' - read -p 'SID: ' sysid -done +echo 'Latest Azure Sentinel data connector downloaded successfully.' -read -p 'Client: ' clientvar -while [ ${#clientvar} -ne 3 ] -do - echo 'Invalid Client - try again' - read -p 'Client: ' clientvar -done - -echo ' -Testing network access to SAP instance' -timeout 2 nc -z $hostvar 33$sysnrvar >/dev/null -portcheck1=$? - -if [ ! $portcheck1 -eq 0 ] -then - echo "Port 33$sysnrvar is not accessible. Allow access and run this script again." - exit 1 +if [ "$CONNECTIONMODE" == 'abap' ]; then + read_value ABAPSERVER 'ABAP Server Hostname' +elif [ "$CONNECTIONMODE" == 'mserv' ]; then + read_value MESSAGESERVERHOST 'Message Server Hostname' + read_value MESSAGESERVERPORT 'Message Server Service Name (port)' + read_value LOGONGROUP 'Logon Group' fi -timeout 2 nc -z $hostvar 32$sysnrvar -portcheck2=$? -if [ ! $portcheck2 -eq 0 ] -then - echo "Port 32$sysnrvar is not accessible. Allow access and run this script again." - exit 1 -fi -echo 'SAP system is reachable -' +read_value SYSTEMNR 'System Number' -sysfileloc=$(pwd)/$containername/$sysid/ -mkdir -p $sysfileloc -if [ ! $? -eq 0 ]; -then +if [ -z "$SID" ]; then + read -r -p 'SID : ' SID + while [ ${#SID} -ne 3 ]; do + echo 'Invalid SID, SID length should be 3' + read -r -p 'SID: ' SID + done +fi + +if [ -z "$CLIENTNUMBER" ]; then + read -r -p 'Client: ' CLIENTNUMBER + while [ ${#CLIENTNUMBER} -ne 3 ]; do + echo 'Invalid Client number, Client number length should be 3' + read -r -p 'Client: ' CLIENTNUMBER + done +fi + +if [ "$CONNECTIONMODE" == 'abap' ] && [ ! $USESNC ]; then + portnumber=32$SYSTEMNR +elif [ "$CONNECTIONMODE" == 'abap' ] && [ $USESNC ]; then + portnumber=48$SYSTEMNR +elif [ "$CONNECTIONMODE" == 'mserv' ]; then + portnumber=$MESSAGESERVERPORT +fi + +if [ "$CONNECTIONMODE" == 'abap' ]; then + echo 'Testing network access to ABAP server' + timeout 2 nc -z "$ABAPSERVER" "$portnumber" >/dev/null 2>&1 + portcheck1=$? +elif [ "$CONNECTIONMODE" == 'mserv' ]; then + echo 'Testing network access to Message server' + timeout 2 nc -z "$MESSAGESERVERHOST" "$portnumber" >/dev/null 2>&1 + portcheck1=$? +fi + +if [ ! $portcheck1 -eq 0 ]; then + echo "Port $portnumber is not accessible. Allow access and run this script again." + exit 1 +else + echo 'SAP system is reachable' +fi + +sysfileloc=$CONFIGPATH/$containername/$SID/ +sudo mkdir -p "$sysfileloc" +sudo chown "$USER" "$sysfileloc" +if [ ! $? -eq 0 ]; then echo 'Error creating the local folder.' exit 1 fi -containername="$containername-$sysid" +# If SNC is used, copy files required for SNC inside container mountpoint. +# Container init script looks for the specific location (config folder/sec) and specific filenames (client.crt, client.key, server.crt etc) +if [ $USESNC ]; then + # Cleanup old data, if exists + if [ -d "$sysfileloc"sec ]; then + sudo rm -rf "$sysfileloc"sec + fi + sudo mkdir -p "$sysfileloc"sec + sudo chown "$USER" "$sysfileloc"sec -sudo docker create -v $sysfileloc:/sapcon-app/sapcon/config/system --name $containername $dockerimage$tagver >/dev/null -if [ $? -eq 1 ]; -then - echo ' -Azure Sentinel SAP connector is already installed. The previous connector will be removed and replaced by the new version.' - pause 'Press any key to update' - sudo docker stop $containername >/dev/null - sudo docker container rm $containername >/dev/null - sudo docker create -v $sysfileloc:/sapcon-app/sapcon/config/system --name $containername $dockerimage >/dev/null - echo 'Azure Sentinel SAP connector was updated for instance '"$sysid" - pause 'Press any key to continue' + if [ -f "$CLIENTPFX" ]; then + #PFX file exists. unpack it + openssl pkcs12 -in "$CLIENTPFX" -out "$sysfileloc"sec/client.p12 -nodes -passin pass:$CLIENTPFXPWD + fi + + if [ ! -f "$CLIENTPFX" ]; then + #CRT/KEY file go concatenated to client.p12 + cat "$CLIENTCERT" "$CLIENTKEY" >"$sysfileloc"sec/client.p12 + fi + + if [ -n "${TRUSTEDCA[0]}" ]; then + # Add any CAs to be trusted + for i in "${TRUSTEDCA[@]}"; do + : + if [ -z "$RLINE" ]; then + RLINE="-r $i" + mkdir "$sysfileloc"sec/ca + else + RLINE+=" -r $i" + fi + cp "$i" "$sysfileloc"sec/ca/ + done + fi + chmod +x "$SAPGENPSE" + sapgenpseresult=$(echo -e "\n" | "$SAPGENPSE" import_p12 -p "$sysfileloc"sec/snc.pse $RLINE "$sysfileloc"sec/client.p12 2>&1) + if [ ! $? -eq 0 ]; then + #sapgenpse failed + echo "Generating PSE environment failed. Failure reason:" + echo "$sapgenpseresult" + exit 1 + fi + + #Not doing anything for now, as in kvmi and kvsi modes client key is stored on disk for now + #if [ "$MODE" == "kvmi" ] || [ "$MODE" == "kvsi" ]; then + #az keyvault certificate import --vault-name "$kv" -n "$SID"-USERCERT -f "$sysfileloc"sec/client.p12 + #Figure out name of the KV item + # rm "$sysfileloc"sec/client.p12 + #fi + cp "$SAPCRYPTOLIB" "$sysfileloc"sec/libsapcrypto.so + cp "$SERVERCERT" "$sysfileloc"sec/server.crt + cp "$SAPGENPSE" "$sysfileloc"sec/sapgenpse + chmod -R 600 "$sysfileloc"sec/* + chmod 700 "$sysfileloc"sec/libsapcrypto.so + chmod 700 "$sysfileloc"sec/sapgenpse + chmod 700 "$sysfileloc"sec + sudo chown root:root "$sysfileloc"sec fi +containername="$containername-$SID" -sudo docker cp $containername:/sapcon-app/template/systemconfig-kickstart.ini "$sysfileloc"systemconfig.ini -if [ ! $? -eq 0 ]; -then +sudo docker inspect "$containername" >/dev/null 2>&1 +if [ $? -eq 0 ]; then + echo 'Azure Sentinel SAP connector is already installed. The previous connector will be removed and replaced by the new version.' + pause 'Press any key to update' + sudo docker stop "$containername" >/dev/null + sudo docker container rm "$containername" >/dev/null +fi +sncline="" +if [ $USESNC ]; then + sncline="-e SECUDIR=/sapcon-app/sapcon/config/system/sec/" +fi + +if [ -n "$HTTPPROXY" ]; then + httpproxyline="-e HTTP_PROXY=$HTTPPROXY" +fi +if [ "$MODE" == "kvmi" ]; then + echo "Creating docker container for use with Azure Key vault and managed VM identity" + sudo docker create -v "$sysfileloc":/sapcon-app/sapcon/config/system $sncline $httpproxyline --name "$containername" $dockerimage$tagver >/dev/null +elif [ "$MODE" == "kvsi" ]; then + echo "Creating docker container for use with Azure Key vault and application authentication" + sudo docker create -v "$sysfileloc":/sapcon-app/sapcon/config/system $sncline $httpproxyline -e AZURE_CLIENT_ID="$APPID" -e AZURE_CLIENT_SECRET="$APPSECRET" -e AZURE_TENANT_ID="$TENANT" --name "$containername" $dockerimage$tagver >/dev/null +elif [ "$MODE" == "cfgf" ]; then + echo "Creating docker container for use with secrets in config file" + sudo docker create -v "$sysfileloc":/sapcon-app/sapcon/config/system $sncline $httpproxyline --name "$containername" $dockerimage$tagver >/dev/null +fi +echo 'Azure Sentinel SAP connector was updated for instance '"$SID" + +sudo docker cp "$containername":/sapcon-app/template/systemconfig-kickstart-blank.ini "$sysfileloc$sysconf" +if [ ! $? -eq 0 ]; then echo 'Error accessing the local folder.' exit 1 fi -echo 'Enter the key vault name followed by your SAP and Azure Sentinel credentials. -Make sure that this VM has managed identity set with the relevant authentication for your Key Vault.' +if [ ! $USESNC ]; then + if [ -z $uservar ]; then + read -rp 'SAP Username: ' uservar + while [ -z "$uservar" ]; do + echo 'SAP Username is empty - try again' + read -rp 'SAP Username: ' uservar + done + uservar=$(echo "$uservar" | tr '[:upper:]' '[:lower:]') + fi -read -p 'KeyVault Name: ' kv -while [ -z $kv ] -do - echo 'KeyVault is empty - try again' - read -p 'KeyVault: ' kv -done + if [ "$uservar" == 'sap*' ]; then + pause 'Note: Using sap* as the connector user may create additional alerts. Press ENTER to continue.' + fi -read -rp 'SAP Username: ' uservar -while [ -z "$uservar" ] -do - echo 'SAP Username is empty - try again' - read -rp 'SAP Username: ' uservar -done - -uservar=$(echo "$uservar" | tr '[:upper:]' '[:lower:]') - -if [ "$uservar" == 'sap*' ] -then - pause 'Note: Using sap* as the connector user may create additional alerts. Press ENTER to continue.' + #echo -n 'SAP Password: ' + read_password passvar "SAP Password" + while [ -z "$passvar" ]; do + echo 'SAP Password empty - try again' + read_password passvar "SAP Password" + done fi - -read -rsp 'SAP Password: ' passvar -while [ -z "$passvar" ] -do - echo 'SAP Password empty - try again' - read -rsp 'SAP Password: ' passvar -done -echo '' -read -p 'Log Analytics Workspace ID : ' logwsid -while [ -z $logwsid ] -do - echo 'Log Analytics workspace ID is empty - try again' - read -p 'Log Analytics Workspace ID : ' logwsid -done - -read -sp 'Log Analytics Public Key: ' logpubkey -while [ -z $logpubkey ] -do - echo 'Log Analytics Public Key is empty - try again' - read -sp 'Log Analytics Public Key: ' logpubkey -done - -sed -i 's//'"$kv"'/1' $sysfileloc$sysconf -sed -i 's//'"$hostvar"'/1' $sysfileloc$sysconf -sed -i 's//'"$sysnrvar"'/1' $sysfileloc$sysconf -sed -i 's//'"$clientvar"'/1' $sysfileloc$sysconf -sed -i 's//'"$sysid"'/1' $sysfileloc$sysconf -sed -i 's//'"$sysid"'/1' $sysfileloc$sysconf - -az keyvault secret set --name $sysid-ABAPPASS --value "$passvar" --description SECRET_ABAP_PASS --vault-name $kv >/dev/null -if [ ! $? -eq 0 ]; -then - echo 'Make sure the key vault has a read/write policy configured for the VM managed identity.' - exit 1 -fi -az keyvault secret set --name $sysid-ABAPUSER --value "$uservar" --description SECRET_ABAP_USER --vault-name $kv >/dev/null -az keyvault secret set --name $sysid-LOGWSID --value "$logwsid" --description SECRET_LOGWSID --vault-name $kv >/dev/null -az keyvault secret set --name $sysid-LOGWSPUBLICKEY --value "$logpubkey" --description SECRET_LOGWSPUBKEY --vault-name $kv >/dev/null - -echo ' -System information and credentials Has been Updated -' - -sdkfileloc=$(sudo find $(pwd) -name "nwrfc*.zip" -type f | head -1) - -if [ -z $sdkfileloc ] -then - echo ' -Enter the full file location path of your downloaded SAP NetWeaver SDK zip. To download the SDK use the following link: https://launchpad.support.sap.com/#/softwarecenter/template/products/%20_APP=00200682500000001943&_EVENT=DISPHIER&HEADER=Y&FUNCTIONBAR=N&EVENT=TREE&NE=NAVIGATE&ENR=01200314690100002214&V=MAINT&TA=ACTUAL&PAGE=SEARCH/SAP%20NW%20RFC%20SDK - - -Select SAP NW RFC SDK 7.50 -> Linux on X86_64 64BIT -> Download the latest version - -Example: /home/user/nwrfc750P_x-70002752.zip' - - read -p 'SDK file location: ' sdkfileloc - - while [ ! -f "$sdkfileloc" ]; - do - echo " - ----file $sdkfileloc does not exist----" - echo ' -Enter the full file location path of your downloaded SAP NetWeaver SDK zip. To download the SDK, use the following link: https://launchpad.support.sap.com/#/softwarecenter/template/products/%20_APP=00200682500000001943&_EVENT=DISPHIER&HEADER=Y&FUNCTIONBAR=N&EVENT=TREE&NE=NAVIGATE&ENR=01200314690100002214&V=MAINT&TA=ACTUAL&PAGE=SEARCH/SAP%20NW%20RFC%20SDK - -Select SAP NW RFC SDK 7.50 -> Linux on X86_64 64BIT -> Download the latest version - -Example: /home/user/nwrfc750P_x-70002752.zip' - - read -p 'SDK file location: ' sdkfileloc +if [ -z "$logwsid" ]; then + read -r -p 'Log Analytics Workspace ID : ' logwsid + while [ -z "$logwsid" ]; do + echo 'Log Analytics workspace ID is empty - try again' + read -r -p 'Log Analytics Workspace ID : ' logwsid done fi -unzip > /dev/null 2>&1 +read_password logpubkey 'Log Analytics Public Key' +while [ -z "$logpubkey" ]; do + echo 'Log Analytics Public Key empty- try again' + read_password logpubkey 'Log Analytics Public Key' +done + +#try to locate the SDK file in current folder +if [ -z "$SDKFILELOC" ]; then + SDKFILELOC=$(ls -1 nwrfc*.zip | head -1) + #try to locate the SDK file in home dir + if [ -z "$SDKFILELOC" ]; then + SDKFILELOC=$(sudo find "$(pwd)" -name "nwrfc*.zip" -type f | head -1) + fi +fi + +while [ -z "$SDKFILELOC" ] || [ ! -f "$SDKFILELOC" ]; do + echo 'Enter the full file location path of your downloaded SAP NetWeaver SDK zip. To download the SDK use the following link:\n https://launchpad.support.sap.com/#/softwarecenter/template/products/%20_APP=00200682500000001943&_EVENT=DISPHIER&HEADER=Y&FUNCTIONBAR=N&EVENT=TREE&NE=NAVIGATE&ENR=01200314690100002214&V=MAINT&TA=ACTUAL&PAGE=SEARCH/SAP%20NW%20RFC%20SDK \nSelect SAP NW RFC SDK 7.50 -> Linux on X86_64 64BIT -> Download the latest version\nExample: /home/user/nwrfc750P_x-70002752.zip' + SDKFILELOC="" + read_value SDKFILELOC 'SDK file location' + SDKFILELOC="${SDKFILELOC/#\~/$HOME}" +done + +unzip >/dev/null 2>&1 ifunzip=$? - -if [ $ifunzip -eq 0 ] -then - unzip -Z1 $sdkfileloc | grep nwrfcsdk/demo/sso2sample.c > /dev/null 2>&1 +if [ $ifunzip -eq 0 ]; then + unzip -Z1 "$SDKFILELOC" | grep nwrfcsdk/demo/sso2sample.c >/dev/null 2>&1 sdkok=$? - sdknum=$(unzip -Z1 $sdkfileloc | wc -l) -else - if [ $(du "$sdkfileloc" | awk '{print $1+0}') -ge 13000 ] - then - sdkok=0 + sdknum=$(unzip -Z1 "$SDKFILELOC" | wc -l) +else + if [ "$(du "$SDKFILELOC" | awk '{print $1+0}')" -ge 13000 ]; then + sdkok=0 sdknum=35 - else + else sdkok=1 fi fi -while [ $? -eq 1 ] || [ $sdkok -eq 1 ] || [ ! $sdknum -ge 20 ] ; -do +while [ $? -eq 1 ] || [ $sdkok -eq 1 ] || [ ! $sdknum -ge 20 ]; do echo 'Invalid NetWeaver SDK, possibly an incorrect or corrupt file. Download the SDK and try again.' - read -p 'SDK file location: ' sdkfileloc - if [ $ifunzip -eq 0 ] - then - unzip -Z1 $sdkfileloc | grep nwrfcsdk/demo/sso2sample.c > /dev/null + read -r -p 'SDK file location: ' SDKFILELOC + if [ $ifunzip -eq 0 ]; then + unzip -Z1 "$SDKFILELOC" | grep nwrfcsdk/demo/sso2sample.c >/dev/null sdkok=$? - sdknum=$(unzip -Z1 $sdkfileloc | wc -l) - else - if [ $(du "$sdkfileloc" | awk '{print $1+0}') -ge 13000 ] - then - sdkok=0 - sdknum=34 - else + sdknum=$(unzip -Z1 "$SDKFILELOC" | wc -l) + else + if [ "$(du "$SDKFILELOC" | awk '{print $1+0}')" -ge 13000 ]; then + sdkok=0 + sdknum=34 + else sdkok=1 fi fi done -sudo docker cp $sdkfileloc $containername:/sapcon-app/inst/ >/dev/null -if [ $? -eq 0 ]; -then +## Parameter read complete, defining configuration file + +if [ "$CONNECTIONMODE" == 'abap' ]; then + # '/\[Azure Credentials\]/a'"loganalyticswsid = $logwsid"'' "$sysfileloc"$sysconf + sed -i '/\[ABAP Central Instance]/a'"ashost=$ABAPSERVER"'' "$sysfileloc"$sysconf +elif [ "$CONNECTIONMODE" == 'mserv' ]; then + sed -i '/\[ABAP Central Instance]/a'"mshost=$MESSAGESERVERHOST"'' "$sysfileloc"$sysconf + sed -i '/\[ABAP Central Instance]/a'"msserv=$MESSAGESERVERHOST"'' "$sysfileloc"$sysconf + sed -i '/\[ABAP Central Instance]/a'"group=$LOGONGROUP"'' "$sysfileloc"$sysconf +fi + +sed -i '/\[ABAP Central Instance]/a'"sysnr=$SYSTEMNR"'' "$sysfileloc"$sysconf +sed -i '/\[ABAP Central Instance]/a'"client=$CLIENTNUMBER"'' "$sysfileloc"$sysconf +sed -i '/\[ABAP Central Instance]/a'"sysid=$SID"'' "$sysfileloc"$sysconf + +if [ "$MODE" == 'kvmi' ] || [ "$MODE" == 'kvsi' ]; then + + sed -i '/\[Secrets Source]/a'"secrets=AZURE_KEY_VAULT"'' "$sysfileloc"$sysconf + sed -i '/\[Secrets Source]/a'"intprefix=$SID"'' "$sysfileloc"$sysconf + sed -i '/\[Secrets Source]/a'"keyvault=$kv"'' "$sysfileloc"$sysconf + + if [ ! $USESNC ]; then + az keyvault secret set --name "$SID"-ABAPPASS --value "$passvar" --description SECRET_ABAP_PASS --vault-name "$kv" >/dev/null + az keyvault secret set --name "$SID"-ABAPUSER --value "$uservar" --description SECRET_ABAP_USER --vault-name "$kv" >/dev/null + fi + az keyvault secret set --name "$SID"-LOGWSID --value "$logwsid" --description SECRET_LOGWSID --vault-name "$kv" >/dev/null + if [ ! $? -eq 0 ]; then + echo 'Make sure the key vault has a read/write policy configured for the VM managed identity.' + exit 1 + fi + az keyvault secret set --name "$SID"-LOGWSPUBLICKEY --value "$logpubkey" --description SECRET_LOGWSPUBKEY --vault-name "$kv" >/dev/null +elif [ "$MODE" == 'cfgf' ]; then + sed -i '/\[Secrets Source]/a'"secrets=DOCKER_FIXED"'' "$sysfileloc"$sysconf + sed -i '/\[Azure Credentials\]/a'"loganalyticswsid = $logwsid"'' "$sysfileloc"$sysconf + sed -i '/\[Azure Credentials\]/a'"publickey = $logpubkey"'' "$sysfileloc"$sysconf + if [ ! $USESNC ]; then + sed -i '/\[ABAP Central Instance]/a'"user=$uservar"'' "$sysfileloc"$sysconf + sed -i '/\[ABAP Central Instance]/a'"passwd=$passvar"'' "$sysfileloc"$sysconf + else + #workaround for blank username with SNC used causing a fail during audit log collection + sed -i '/\[ABAP Central Instance]/a'"user="'' "$sysfileloc"$sysconf + fi +fi + +if [ $USESNC ]; then + sed -i '/\[ABAP Central Instance]/a'"snc_lib=\/sapcon-app\/sapcon\/config\/system\/sec\/libsapcrypto.so"'' "$sysfileloc"$sysconf + MYCERT=$(openssl x509 -in $CLIENTCERT | tr -d '\r\n' | sed -E 's/-+BEGIN CERTIFICATE-+//' | sed -E 's/-+END CERTIFICATE-+//' | sed 's/\//\\\//g') + sed -i '/\[ABAP Central Instance]/a'"x509cert=$MYCERT"'' "$sysfileloc"$sysconf + PARTNERNAME=$(openssl x509 -in "$SERVERCERT" -text -noout | grep Subject: | awk -F: '{print $2}') + sed -i '/\[ABAP Central Instance]/a'"snc_partnername=p:$PARTNERNAME"'' "$sysfileloc"$sysconf +fi + +echo 'System information and credentials Has been Updated' + +sudo docker cp "$SDKFILELOC" "$containername":/sapcon-app/inst/ >/dev/null +if [ $? -eq 0 ]; then echo 'SDK archive was successfully updated' -else +else echo 'Azure Sentinel data connector upgrade failed. The NetWeaver SDK could not be added to the image' exit 1 fi - -sudo docker start $containername >/dev/null -if [ $? -eq 0 ]; -then +sudo docker start "$containername" >/dev/null +if [ $? -eq 0 ]; then echo ' Azure Sentinel SAP connector was started - quick reference for future steps: View logs: docker logs '"$containername"' @@ -372,8 +857,8 @@ Stop the connector: docker stop '"$containername"' Start the connector: docker start '"$containername"' The process has been successfully completed, thank you!' else - echo 'Azure Sentinel Connector upgrade failed – the NetWeaver SDK could not be added to the image' + echo 'Azure Sentinel Connector upgrade failed - the NetWeaver SDK could not be added to the image' exit 1 fi # Docker Configurations -newgrp docker +newgrp docker diff --git a/Solutions/SecurityBridge/Package/1.0.0.zip b/Solutions/SecurityBridge/Package/1.0.0.zip deleted file mode 100644 index 4e0bff4f63..0000000000 Binary files a/Solutions/SecurityBridge/Package/1.0.0.zip and /dev/null differ diff --git a/Solutions/SecurityBridge/Package/1.0.1.zip b/Solutions/SecurityBridge/Package/1.0.1.zip new file mode 100644 index 0000000000..23f5296171 Binary files /dev/null and b/Solutions/SecurityBridge/Package/1.0.1.zip differ diff --git a/Solutions/SecurityBridge/Package/mainTemplate.json b/Solutions/SecurityBridge/Package/mainTemplate.json index a3607803f8..ab767c7911 100644 --- a/Solutions/SecurityBridge/Package/mainTemplate.json +++ b/Solutions/SecurityBridge/Package/mainTemplate.json @@ -53,7 +53,7 @@ }, "connector1-name": { "type": "string", - "defaultValue": "fea66c27-7312-46af-8e6f-5a35dd296155" + "defaultValue": "079ce073-24d3-4a8a-8a55-7703ca211aab" } }, "variables": { @@ -80,7 +80,7 @@ "apiVersion": "2021-08-01", "properties": { "displayName": "[concat(parameters('workbook1-name'), ' - ', parameters('formattedTimeNow'))]", - "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"## Gain insights into SecurityBridge logs.\\n---\\n\\nSecurityBridge is the first and only holistic, natively integrated security platform, addressing all aspects needed to protect organizations running SAP from internal and external threats against their core business applications. The SecurityBridge platform is an SAP-certified add-on, used by organizations around the globe, and addresses the clients’ need for advanced cybersecurity, real-time monitoring, compliance, code security, and patching to protect against internal and external threats.This Microsoft Sentinel Solution allows you to integrate SecurityBridge Threat Detection events from all your on-premise and cloud based SAP instances into your security monitoring.Use this Microsoft Sentinel Solution to receive normalized and speaking security events, pre-built dashboards and out-of-the-box templates for your SAP security monitoring.\\nThis data connector depends on a parser based on a Kusto Function to work as expected. [Follow these steps](https://aka.ms/sentinel-SecurityBridgeLogs-parser) to create the Kusto Functions alias, SecurityBridgeLogs\"},\"name\":\"text - 2\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"961f51be-788f-4f9a-b2a0-0a596216d59f\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"isRequired\":true,\"value\":{\"durationMs\":604800000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":300000},{\"durationMs\":900000},{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":14400000},{\"durationMs\":43200000},{\"durationMs\":86400000},{\"durationMs\":172800000},{\"durationMs\":259200000},{\"durationMs\":604800000},{\"durationMs\":1209600000},{\"durationMs\":2419200000},{\"durationMs\":2592000000},{\"durationMs\":5184000000},{\"durationMs\":7776000000}],\"allowCustom\":true},\"timeContext\":{\"durationMs\":86400000}},{\"id\":\"e49c1a95-361b-4a51-8207-1dda7041d855\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Help\",\"label\":\"Show Help\",\"type\":10,\"isRequired\":true,\"typeSettings\":{\"showDefault\":false},\"jsonData\":\"[{ \\\"value\\\": \\\"Yes\\\", \\\"label\\\": \\\"Yes\\\"},\\r\\n {\\\"value\\\": \\\"No\\\", \\\"label\\\": \\\"No\\\", \\\"selected\\\":true }]\"},{\"id\":\"51cb8cb1-3d50-47f4-9485-2519a992c735\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"urlprefix\",\"label\":\"URL Prefix\",\"type\":1,\"description\":\"Add the url prefix of the system to view the links for events\",\"isRequired\":true,\"value\":\"\\\"http://abex3.abap-experts.com:8003/sap/bc/ui5_ui5/abex/sefwmd/#/events/details/\\\"\"}],\"style\":\"above\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 2\"},{\"type\":11,\"content\":{\"version\":\"LinkItem/1.0\",\"style\":\"tabs\",\"links\":[{\"id\":\"38cf22e5-8dc6-477e-8e6c-c8107de22596\",\"cellValue\":\"Tab\",\"linkTarget\":\"parameter\",\"linkLabel\":\"Events Monitor\",\"subTarget\":\"monitor\",\"style\":\"link\"},{\"id\":\"2e2baa8d-3b34-4818-a3c7-df5c179f6385\",\"cellValue\":\"Tab\",\"linkTarget\":\"parameter\",\"linkLabel\":\"Events Analyze\",\"subTarget\":\"analyze\",\"style\":\"link\"}]},\"name\":\"links - 22\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| extend Severity = tostring(Severity)\\r\\n| summarize Count = count() by Severity\\r\\n| extend SeverityNumber = case(Severity == \\\"Low\\\", 3, Severity == \\\"Medium\\\", 7, Severity == \\\"High\\\", 9, Severity == \\\"Critical\\\", 10, 0)\\r\\n| sort by SeverityNumber\",\"size\":4,\"title\":\"Events by Severity\",\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"Severity\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"==\",\"thresholdValue\":\"Low\",\"representation\":\"Sev3\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Medium\",\"representation\":\"Sev2\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"High\",\"representation\":\"Sev1\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Critical\",\"representation\":\"Sev0\",\"text\":\"{0}{1}\"},{\"operator\":\"Default\",\"representation\":\"Sev4\",\"text\":\"{0}{1}\"}]}},\"leftContent\":{\"columnMatch\":\"Count\",\"formatter\":1},\"showBorder\":false},\"graphSettings\":{\"type\":0,\"topContent\":{\"columnMatch\":\"Severity\",\"formatter\":1},\"centerContent\":{\"columnMatch\":\"count_\",\"formatter\":1,\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}}}},\"name\":\"query - 3\"},{\"type\":1,\"content\":{\"json\":\"Select the filters below to display relevant events\",\"style\":\"info\"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 3\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"63aff516-725f-4c6c-bb0a-b2bb484176d1\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Severity\",\"type\":2,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| extend Severity = tostring(Severity)\\r\\n| distinct Severity\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"afb7a9f8-5e29-411e-8d9e-99f4bc855b0b\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"User\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct duser\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"57735ba8-7c80-477c-899c-b0507bacb946\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"SAPSID\",\"label\":\"SAP SID\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct SAPsid\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":604800000},\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"b6d548e0-6685-4bac-9419-25d74a4972d7\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Terminal\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct shost\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":604800000},\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"60ff9487-e9a9-4c08-9207-8d7c8b186f91\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Listener\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct DeviceEventClassID\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":604800000},\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"1521e9a7-53ea-4737-8e8e-819599655b13\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Action\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct Name\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":604800000},\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| where duser in ({User}) or \\\"*\\\" in ({User})\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| where shost in ({Terminal}) or \\\"*\\\" in ({Terminal})\\r\\n| where DeviceEventClassID in ({Listener}) or \\\"*\\\" in ({Listener})\\r\\n| where Name in ({Action}) or \\\"*\\\" in ({Action})\\r\\n| project TimeGenerated, Severity, DeviceEventClassID, Name, msg, [\\\"Link to Event\\\"]= strcat(({urlprefix}), externalid), shost, duser, SAPsid, SAPclient\\r\\n| sort by TimeGenerated\",\"size\":0,\"title\":\"Event by Selected Filters\",\"timeContext\":{\"durationMs\":604800000},\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Link to Event\",\"formatter\":7,\"formatOptions\":{\"linkTarget\":\"Url\",\"linkLabel\":\"Link to the Event\"}}],\"sortBy\":[{\"itemKey\":\"shost\",\"sortOrder\":2}]},\"sortBy\":[{\"itemKey\":\"shost\",\"sortOrder\":2}]},\"name\":\"query - 1\"}]},\"conditionalVisibility\":{\"parameterName\":\"Tab\",\"comparison\":\"isEqualTo\",\"value\":\"analyze\"},\"name\":\"group - 23\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":1,\"content\":{\"json\":\"This tab helps in analyzing events.\",\"style\":\"info\"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 10\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"a0a31cee-67ce-43c1-b0e5-a4f744edf81e\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"SAPSID\",\"label\":\"SAP SID\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| distinct SAPsid\",\"value\":[\"value::all\"],\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 0\"},{\"type\":1,\"content\":{\"json\":\"This bar chart shows the events by event name.\",\"style\":\"info\"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by Name\",\"size\":0,\"title\":\"Events by Event Name\",\"timeContext\":{\"durationMs\":604800000},\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"name\":\"query - 1\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":1,\"content\":{\"json\":\"This barchart shows the events ingestion with respect to time\",\"style\":\"info\"},\"customWidth\":\"100\",\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 12\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize [\\\"Number of Events\\\"] = count() by bin(todatetime(rt), 1d)\",\"size\":1,\"title\":\"Events Ingestion by Time\",\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\",\"chartSettings\":{\"showLegend\":true}},\"customWidth\":\"100\",\"name\":\"query - 1 - Copy - Copy\"}]},\"customWidth\":\"50\",\"name\":\"group - 13\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":1,\"content\":{\"json\":\"This barchart shows the events ingestion with respect to severity and time\",\"style\":\"info\"},\"customWidth\":\"100\",\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 12\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by bin(todatetime(rt), 1h), Severity\",\"size\":1,\"title\":\"Events by Time with respect to Severity\",\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true,\"seriesLabelSettings\":[{\"seriesName\":\"Medium\",\"color\":\"yellow\"},{\"seriesName\":\"High\",\"color\":\"redBright\"},{\"seriesName\":\"Critical\",\"color\":\"red\"},{\"seriesName\":\"Low\",\"color\":\"blueDark\"}]}},\"customWidth\":\"100\",\"name\":\"query - 1 - Copy\"}]},\"customWidth\":\"50\",\"name\":\"group - 13 - Copy\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":1,\"content\":{\"json\":\"This barchart shows the events ingestion with respect to SAPsid\",\"style\":\"info\"},\"customWidth\":\"100\",\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 12\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by SAPsid\",\"size\":1,\"title\":\"Events Ingestion by Time\",\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\",\"chartSettings\":{\"showLegend\":true}},\"customWidth\":\"100\",\"name\":\"query - 1 - Copy - Copy\"}]},\"customWidth\":\"50\",\"name\":\"group - 13 - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by Severity\",\"size\":0,\"title\":\"Events by Severity\",\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"30\",\"name\":\"query - 1 - Copy - Copy - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by duser\\r\\n| sort by count_\\r\\n| take 5\",\"size\":0,\"title\":\"Top 5 Users\",\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"30\",\"name\":\"query - 1 - Copy - Copy - Copy - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by dhost\\r\\n| sort by count_\\r\\n| take 5\",\"size\":0,\"title\":\"Top 5 Workstations\",\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"30\",\"name\":\"query - 1 - Copy - Copy - Copy - Copy - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by duser\\r\\n| join (\\r\\nSecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| extend user = duser\\r\\n| make-series TrendList = count() on todatetime(rt) in range({TimeRange:start}, {TimeRange:end}, {TimeRange:grain}) by duser ) on duser\\r\\n| project duser, [\\\"Total events\\\"] = count_, TrendLine = TrendList\\r\\n| top 10 by [\\\"Total events\\\"] desc\",\"size\":0,\"title\":\"Event Stats by Users\",\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"TrendLine\",\"formatter\":9,\"formatOptions\":{\"palette\":\"green\"}}]},\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"50\",\"name\":\"query - 1 - Copy - Copy - Copy - Copy - Copy - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by dhost\\r\\n| join (\\r\\nSecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| extend user = dhost\\r\\n| make-series TrendList = count() on todatetime(rt) in range({TimeRange:start}, {TimeRange:end}, {TimeRange:grain}) by dhost ) on dhost\\r\\n| project dhost, [\\\"Total events\\\"] = count_, TrendLine = TrendList\\r\\n| top 10 by [\\\"Total events\\\"] desc\",\"size\":0,\"title\":\"Event Stats by Host\",\"timeContext\":{\"durationMs\":604800000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"TrendLine\",\"formatter\":9,\"formatOptions\":{\"palette\":\"green\"}}]},\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"50\",\"name\":\"query - 1 - Copy - Copy - Copy - Copy - Copy - Copy - Copy\"}]},\"conditionalVisibility\":{\"parameterName\":\"Tab\",\"comparison\":\"isEqualTo\",\"value\":\"monitor\"},\"name\":\"group - 24\"}],\"fromTemplateId\":\"sentinel-SecurityBridge\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\r\n", + "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"## Gain insights into SecurityBridge logs.\\n---\\n\\nSecurityBridge is the first and only holistic, natively integrated security platform, addressing all aspects needed to protect organizations running SAP from internal and external threats against their core business applications. The SecurityBridge platform is an SAP-certified add-on, used by organizations around the globe, and addresses the clients’ need for advanced cybersecurity, real-time monitoring, compliance, code security, and patching to protect against internal and external threats.This Microsoft Sentinel Solution allows you to integrate SecurityBridge Threat Detection events from all your on-premise and cloud based SAP instances into your security monitoring.Use this Microsoft Sentinel Solution to receive normalized and speaking security events, pre-built dashboards and out-of-the-box templates for your SAP security monitoring.\\nThis data connector depends on a parser based on a Kusto Function to work as expected. [Follow these steps](https://aka.ms/sentinel-SecurityBridgeLogs-parser) to create the Kusto Functions alias, SecurityBridgeLogs\"},\"name\":\"text - 2\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"961f51be-788f-4f9a-b2a0-0a596216d59f\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"isRequired\":true,\"value\":{\"durationMs\":5184000000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":300000},{\"durationMs\":900000},{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":14400000},{\"durationMs\":43200000},{\"durationMs\":86400000},{\"durationMs\":172800000},{\"durationMs\":259200000},{\"durationMs\":604800000},{\"durationMs\":1209600000},{\"durationMs\":2419200000},{\"durationMs\":2592000000},{\"durationMs\":5184000000},{\"durationMs\":7776000000}],\"allowCustom\":true},\"timeContext\":{\"durationMs\":86400000}},{\"id\":\"e49c1a95-361b-4a51-8207-1dda7041d855\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Help\",\"label\":\"Show Help\",\"type\":10,\"isRequired\":true,\"typeSettings\":{\"showDefault\":false},\"jsonData\":\"[{ \\\"value\\\": \\\"Yes\\\", \\\"label\\\": \\\"Yes\\\"},\\r\\n {\\\"value\\\": \\\"No\\\", \\\"label\\\": \\\"No\\\", \\\"selected\\\":true }]\",\"value\":\"Yes\"},{\"id\":\"51cb8cb1-3d50-47f4-9485-2519a992c735\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"urlprefix\",\"label\":\"URL Prefix\",\"type\":1,\"description\":\"Add the url prefix of the system to view the links for events\",\"isRequired\":true,\"value\":\"\\\"http://abex3.abap-experts.com:8003/sap/bc/ui5_ui5/abex/sefwmd/#/events/details/\\\"\"}],\"style\":\"above\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 2\"},{\"type\":11,\"content\":{\"version\":\"LinkItem/1.0\",\"style\":\"tabs\",\"links\":[{\"id\":\"38cf22e5-8dc6-477e-8e6c-c8107de22596\",\"cellValue\":\"Tab\",\"linkTarget\":\"parameter\",\"linkLabel\":\"Events Monitor\",\"subTarget\":\"monitor\",\"style\":\"link\"},{\"id\":\"2e2baa8d-3b34-4818-a3c7-df5c179f6385\",\"cellValue\":\"Tab\",\"linkTarget\":\"parameter\",\"linkLabel\":\"Events Analyze\",\"subTarget\":\"analyze\",\"style\":\"link\"}]},\"name\":\"links - 22\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| extend Severity = tostring(Severity)\\r\\n| summarize Count = count() by Severity\\r\\n| extend SeverityNumber = case(Severity == \\\"Low\\\", 3, Severity == \\\"Medium\\\", 7, Severity == \\\"High\\\", 9, Severity == \\\"Critical\\\", 10, 0)\\r\\n| sort by SeverityNumber\",\"size\":4,\"title\":\"Events by Severity\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"Severity\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"==\",\"thresholdValue\":\"Low\",\"representation\":\"Sev3\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Medium\",\"representation\":\"Sev2\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"High\",\"representation\":\"Sev1\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Critical\",\"representation\":\"Sev0\",\"text\":\"{0}{1}\"},{\"operator\":\"Default\",\"representation\":\"Sev4\",\"text\":\"{0}{1}\"}]}},\"leftContent\":{\"columnMatch\":\"Count\",\"formatter\":1},\"showBorder\":false},\"graphSettings\":{\"type\":0,\"topContent\":{\"columnMatch\":\"Severity\",\"formatter\":1},\"centerContent\":{\"columnMatch\":\"count_\",\"formatter\":1,\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}}}},\"name\":\"query - 3\"},{\"type\":1,\"content\":{\"json\":\"Select the filters below to display relevant events\",\"style\":\"info\"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 3\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"63aff516-725f-4c6c-bb0a-b2bb484176d1\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Severity\",\"type\":2,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| extend Severity = tostring(Severity)\\r\\n| distinct Severity\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"afb7a9f8-5e29-411e-8d9e-99f4bc855b0b\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"User\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct duser\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"57735ba8-7c80-477c-899c-b0507bacb946\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"SAPSID\",\"label\":\"SAP SID\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct SAPsid\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"b6d548e0-6685-4bac-9419-25d74a4972d7\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Terminal\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct shost\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"60ff9487-e9a9-4c08-9207-8d7c8b186f91\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Listener\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct DeviceEventClassID\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"1521e9a7-53ea-4737-8e8e-819599655b13\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Action\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| distinct Name\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where Severity in ({Severity})\\r\\n| where duser in ({User}) or \\\"*\\\" in ({User})\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| where shost in ({Terminal}) or \\\"*\\\" in ({Terminal})\\r\\n| where DeviceEventClassID in ({Listener}) or \\\"*\\\" in ({Listener})\\r\\n| where Name in ({Action}) or \\\"*\\\" in ({Action})\\r\\n| project TimeGenerated, Severity, DeviceEventClassID, Name, msg, [\\\"Link to Event\\\"]= strcat(({urlprefix}), externalid), shost, duser, SAPsid, SAPclient\\r\\n| sort by TimeGenerated\",\"size\":0,\"title\":\"Event by Selected Filters\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Link to Event\",\"formatter\":7,\"formatOptions\":{\"linkTarget\":\"Url\",\"linkLabel\":\"Link to the Event\"}}],\"sortBy\":[{\"itemKey\":\"shost\",\"sortOrder\":2}]},\"sortBy\":[{\"itemKey\":\"shost\",\"sortOrder\":2}]},\"name\":\"query - 1\"}]},\"conditionalVisibility\":{\"parameterName\":\"Tab\",\"comparison\":\"isEqualTo\",\"value\":\"analyze\"},\"name\":\"group - 23\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":1,\"content\":{\"json\":\"This tab helps in analyzing events.\",\"style\":\"info\"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 10\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"a0a31cee-67ce-43c1-b0e5-a4f744edf81e\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"SAPSID\",\"label\":\"SAP SID\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"SecurityBridgeLogs\\r\\n| distinct SAPsid\",\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"defaultValue\":\"value::all\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 0\"},{\"type\":1,\"content\":{\"json\":\"This bar chart shows the events by event name.\",\"style\":\"info\"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by Name\",\"size\":0,\"title\":\"Events by Event Name\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"name\":\"query - 1\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":1,\"content\":{\"json\":\"This barchart shows the events ingestion with respect to time\",\"style\":\"info\"},\"customWidth\":\"100\",\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 12\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize [\\\"Number of Events\\\"] = count() by bin(todatetime(rt), 1d)\",\"size\":1,\"title\":\"Events Ingestion by Time\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\",\"chartSettings\":{\"showLegend\":true}},\"customWidth\":\"100\",\"name\":\"query - 1 - Copy - Copy\"}]},\"customWidth\":\"50\",\"name\":\"group - 13\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":1,\"content\":{\"json\":\"This barchart shows the events ingestion with respect to severity and time\",\"style\":\"info\"},\"customWidth\":\"100\",\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 12\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by bin(todatetime(rt), 1h), Severity\",\"size\":1,\"title\":\"Events by Time with respect to Severity\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true,\"seriesLabelSettings\":[{\"seriesName\":\"Medium\",\"color\":\"yellow\"},{\"seriesName\":\"High\",\"color\":\"redBright\"},{\"seriesName\":\"Critical\",\"color\":\"red\"},{\"seriesName\":\"Low\",\"color\":\"blueDark\"}]}},\"customWidth\":\"100\",\"name\":\"query - 1 - Copy\"}]},\"customWidth\":\"50\",\"name\":\"group - 13 - Copy\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":1,\"content\":{\"json\":\"This barchart shows the events ingestion with respect to SAPsid\",\"style\":\"info\"},\"customWidth\":\"100\",\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"name\":\"text - 12\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by SAPsid\",\"size\":1,\"title\":\"Events Ingestion by Time\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"barchart\",\"chartSettings\":{\"showLegend\":true}},\"customWidth\":\"100\",\"name\":\"query - 1 - Copy - Copy\"}]},\"customWidth\":\"50\",\"name\":\"group - 13 - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by Severity\",\"size\":0,\"title\":\"Events by Severity\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"30\",\"name\":\"query - 1 - Copy - Copy - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by duser\\r\\n| sort by count_\\r\\n| take 5\",\"size\":0,\"title\":\"Top 5 Users\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"30\",\"name\":\"query - 1 - Copy - Copy - Copy - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by dhost\\r\\n| sort by count_\\r\\n| take 5\",\"size\":0,\"title\":\"Top 5 Workstations\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\",\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"30\",\"name\":\"query - 1 - Copy - Copy - Copy - Copy - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by duser\\r\\n| join (\\r\\nSecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| extend user = duser\\r\\n| make-series TrendList = count() on todatetime(rt) in range({TimeRange:start}, {TimeRange:end}, {TimeRange:grain}) by duser ) on duser\\r\\n| project duser, [\\\"Total events\\\"] = count_, TrendLine = TrendList\\r\\n| top 10 by [\\\"Total events\\\"] desc\",\"size\":0,\"title\":\"Event Stats by Users\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"TrendLine\",\"formatter\":9,\"formatOptions\":{\"palette\":\"green\"}}]},\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"50\",\"name\":\"query - 1 - Copy - Copy - Copy - Copy - Copy - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| summarize count() by dhost\\r\\n| join (\\r\\nSecurityBridgeLogs\\r\\n| where SAPsid in ({SAPSID}) or \\\"*\\\" in ({SAPSID})\\r\\n| extend user = dhost\\r\\n| make-series TrendList = count() on todatetime(rt) in range({TimeRange:start}, {TimeRange:end}, {TimeRange:grain}) by dhost ) on dhost\\r\\n| project dhost, [\\\"Total events\\\"] = count_, TrendLine = TrendList\\r\\n| top 10 by [\\\"Total events\\\"] desc\",\"size\":0,\"title\":\"Event Stats by Host\",\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"TrendLine\",\"formatter\":9,\"formatOptions\":{\"palette\":\"green\"}}]},\"chartSettings\":{\"showMetrics\":false,\"showLegend\":true}},\"customWidth\":\"50\",\"name\":\"query - 1 - Copy - Copy - Copy - Copy - Copy - Copy - Copy\"}]},\"conditionalVisibility\":{\"parameterName\":\"Tab\",\"comparison\":\"isEqualTo\",\"value\":\"monitor\"},\"name\":\"group - 24\"}],\"fromTemplateId\":\"sentinel-SecurityBridge\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\r\n", "version": "1.0", "sourceId": "[variables('_workbook-source')]", "category": "sentinel" @@ -286,7 +286,7 @@ "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2021-03-01-preview", "properties": { - "version": "1.0.0", + "version": "1.0.1", "kind": "Solution", "contentId": "[variables('_sourceId')]", "parentId": "[variables('_sourceId')]", @@ -311,17 +311,17 @@ { "kind": "Workbook", "contentId": "[variables('_SecurityBridgeThreatDetectionforSAP_workbook')]", - "version": "1.0.0" + "version": "1.0.1" }, { "kind": "Parser", "contentId": "[variables('_SecurityBridgeLogs_Parser')]", - "version": "1.0.0" + "version": "1.0.1" }, { "kind": "DataConnector", "contentId": "[variables('_SecurityBridgeSAPConnector')]", - "version": "1.0.0" + "version": "1.0.1" } ] }, diff --git a/Solutions/SecurityBridge/Solution_SecurityBridgeSAP.json b/Solutions/SecurityBridge/Solution_SecurityBridgeSAP.json index ffba499329..f56a0fec05 100644 --- a/Solutions/SecurityBridge/Solution_SecurityBridgeSAP.json +++ b/Solutions/SecurityBridge/Solution_SecurityBridgeSAP.json @@ -18,6 +18,6 @@ "Data Connectors/Connector_SecurityBridge.json" ], "BasePath": "https://raw.githubusercontent.com/frozenstrawberries/Azure-Sentinel/master/Solutions/SecurityBridge/", - "Version": "1.0.0", + "Version": "1.0.1", "Metadata": "SolutionMetadata.json" } \ No newline at end of file diff --git a/Solutions/SecurityBridge/Workbooks/SecurityBridgeThreatDetectionforSAP.json b/Solutions/SecurityBridge/Workbooks/SecurityBridgeThreatDetectionforSAP.json index e89a4517b9..cb8cac5a2e 100644 --- a/Solutions/SecurityBridge/Workbooks/SecurityBridgeThreatDetectionforSAP.json +++ b/Solutions/SecurityBridge/Workbooks/SecurityBridgeThreatDetectionforSAP.json @@ -20,7 +20,7 @@ "type": 4, "isRequired": true, "value": { - "durationMs": 604800000 + "durationMs": 5184000000 }, "typeSettings": { "selectableValues": [ @@ -87,7 +87,8 @@ "additionalResourceOptions": [], "showDefault": false }, - "jsonData": "[{ \"value\": \"Yes\", \"label\": \"Yes\"},\r\n {\"value\": \"No\", \"label\": \"No\", \"selected\":true }]" + "jsonData": "[{ \"value\": \"Yes\", \"label\": \"Yes\"},\r\n {\"value\": \"No\", \"label\": \"No\", \"selected\":true }]", + "value": "Yes" }, { "id": "51cb8cb1-3d50-47f4-9485-2519a992c735", @@ -145,9 +146,6 @@ "query": "SecurityBridgeLogs\r\n| extend Severity = tostring(Severity)\r\n| summarize Count = count() by Severity\r\n| extend SeverityNumber = case(Severity == \"Low\", 3, Severity == \"Medium\", 7, Severity == \"High\", 9, Severity == \"Critical\", 10, 0)\r\n| sort by SeverityNumber", "size": 4, "title": "Events by Severity", - "timeContext": { - "durationMs": 604800000 - }, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", @@ -253,7 +251,7 @@ "showDefault": false }, "timeContext": { - "durationMs": 604800000 + "durationMs": 7776000000 }, "timeContextFromParameter": "TimeRange", "defaultValue": "value::all", @@ -277,7 +275,7 @@ "showDefault": false }, "timeContext": { - "durationMs": 0 + "durationMs": 7776000000 }, "timeContextFromParameter": "TimeRange", "defaultValue": "value::all", @@ -302,8 +300,9 @@ "showDefault": false }, "timeContext": { - "durationMs": 604800000 + "durationMs": 0 }, + "timeContextFromParameter": "TimeRange", "defaultValue": "value::all", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces" @@ -325,8 +324,9 @@ "showDefault": false }, "timeContext": { - "durationMs": 604800000 + "durationMs": 0 }, + "timeContextFromParameter": "TimeRange", "defaultValue": "value::all", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces" @@ -348,8 +348,9 @@ "showDefault": false }, "timeContext": { - "durationMs": 604800000 + "durationMs": 0 }, + "timeContextFromParameter": "TimeRange", "defaultValue": "value::all", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces" @@ -371,8 +372,9 @@ "showDefault": false }, "timeContext": { - "durationMs": 604800000 + "durationMs": 0 }, + "timeContextFromParameter": "TimeRange", "defaultValue": "value::all", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces" @@ -391,9 +393,7 @@ "query": "SecurityBridgeLogs\r\n| where Severity in ({Severity})\r\n| where duser in ({User}) or \"*\" in ({User})\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| where shost in ({Terminal}) or \"*\" in ({Terminal})\r\n| where DeviceEventClassID in ({Listener}) or \"*\" in ({Listener})\r\n| where Name in ({Action}) or \"*\" in ({Action})\r\n| project TimeGenerated, Severity, DeviceEventClassID, Name, msg, [\"Link to Event\"]= strcat(({urlprefix}), externalid), shost, duser, SAPsid, SAPclient\r\n| sort by TimeGenerated", "size": 0, "title": "Event by Selected Filters", - "timeContext": { - "durationMs": 604800000 - }, + "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "gridSettings": { @@ -467,9 +467,6 @@ "quote": "'", "delimiter": ",", "query": "SecurityBridgeLogs\r\n| distinct SAPsid", - "value": [ - "value::all" - ], "typeSettings": { "additionalResourceOptions": [ "value::all" @@ -477,7 +474,7 @@ "showDefault": false }, "timeContext": { - "durationMs": 604800000 + "durationMs": 0 }, "timeContextFromParameter": "TimeRange", "defaultValue": "value::all", @@ -511,9 +508,7 @@ "query": "SecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| summarize count() by Name", "size": 0, "title": "Events by Event Name", - "timeContext": { - "durationMs": 604800000 - }, + "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "visualization": "barchart", @@ -551,9 +546,6 @@ "query": "SecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| summarize [\"Number of Events\"] = count() by bin(todatetime(rt), 1d)", "size": 1, "title": "Events Ingestion by Time", - "timeContext": { - "durationMs": 604800000 - }, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", @@ -597,9 +589,6 @@ "query": "SecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| summarize count() by bin(todatetime(rt), 1h), Severity", "size": 1, "title": "Events by Time with respect to Severity", - "timeContext": { - "durationMs": 604800000 - }, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", @@ -662,9 +651,6 @@ "query": "SecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| summarize count() by SAPsid", "size": 1, "title": "Events Ingestion by Time", - "timeContext": { - "durationMs": 604800000 - }, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", @@ -688,9 +674,6 @@ "query": "SecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| summarize count() by Severity", "size": 0, "title": "Events by Severity", - "timeContext": { - "durationMs": 604800000 - }, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", @@ -710,9 +693,6 @@ "query": "SecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| summarize count() by duser\r\n| sort by count_\r\n| take 5", "size": 0, "title": "Top 5 Users", - "timeContext": { - "durationMs": 604800000 - }, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", @@ -732,9 +712,6 @@ "query": "SecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| summarize count() by dhost\r\n| sort by count_\r\n| take 5", "size": 0, "title": "Top 5 Workstations", - "timeContext": { - "durationMs": 604800000 - }, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", @@ -754,9 +731,6 @@ "query": "SecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| summarize count() by duser\r\n| join (\r\nSecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| extend user = duser\r\n| make-series TrendList = count() on todatetime(rt) in range({TimeRange:start}, {TimeRange:end}, {TimeRange:grain}) by duser ) on duser\r\n| project duser, [\"Total events\"] = count_, TrendLine = TrendList\r\n| top 10 by [\"Total events\"] desc", "size": 0, "title": "Event Stats by Users", - "timeContext": { - "durationMs": 604800000 - }, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", @@ -787,9 +761,6 @@ "query": "SecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| summarize count() by dhost\r\n| join (\r\nSecurityBridgeLogs\r\n| where SAPsid in ({SAPSID}) or \"*\" in ({SAPSID})\r\n| extend user = dhost\r\n| make-series TrendList = count() on todatetime(rt) in range({TimeRange:start}, {TimeRange:end}, {TimeRange:grain}) by dhost ) on dhost\r\n| project dhost, [\"Total events\"] = count_, TrendLine = TrendList\r\n| top 10 by [\"Total events\"] desc", "size": 0, "title": "Event Stats by Host", - "timeContext": { - "durationMs": 604800000 - }, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces",